diff --git a/backport-0001-CVE-2022-2031-CVE-2022-32744.patch b/backport-0001-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..adcb2df1a1cd31fdfca3f34bb272899492b365e8 --- /dev/null +++ b/backport-0001-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,73 @@ +From 258710a9f2145939d959a8512e0d40dfd32ef1b7 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 5 Aug 2021 13:30:41 +0200 +Subject: [PATCH] CVE-2021-3738 auth_util: avoid talloc_tos() in + copy_session_info() + +We want to use this also in code without existing +stackframe. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14468 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + auth/auth_util.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/auth/auth_util.c b/auth/auth_util.c +index f3586f1fc1e..fe01babd107 100644 +--- a/auth/auth_util.c ++++ b/auth/auth_util.c +@@ -26,26 +26,28 @@ + struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + const struct auth_session_info *src) + { ++ TALLOC_CTX *frame = talloc_stackframe(); + struct auth_session_info *dst; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + + ndr_err = ndr_push_struct_blob( + &blob, +- talloc_tos(), ++ frame, + src, + (ndr_push_flags_fn_t)ndr_push_auth_session_info); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_ERR("copy_session_info(): ndr_push_auth_session_info " + "failed: %s\n", + ndr_errstr(ndr_err)); ++ TALLOC_FREE(frame); + return NULL; + } + + dst = talloc(mem_ctx, struct auth_session_info); + if (dst == NULL) { + DBG_ERR("talloc failed\n"); +- TALLOC_FREE(blob.data); ++ TALLOC_FREE(frame); + return NULL; + } + +@@ -54,15 +56,16 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + dst, + dst, + (ndr_pull_flags_fn_t)ndr_pull_auth_session_info); +- TALLOC_FREE(blob.data); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DBG_ERR("copy_session_info(): ndr_pull_auth_session_info " + "failed: %s\n", + ndr_errstr(ndr_err)); + TALLOC_FREE(dst); ++ TALLOC_FREE(frame); + return NULL; + } + ++ TALLOC_FREE(frame); + return dst; + } +-- +2.33.0 + diff --git a/backport-0001-CVE-2022-32746.patch b/backport-0001-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1e84d792adf05d6910472e223884b9dfd3412f5 --- /dev/null +++ b/backport-0001-CVE-2022-32746.patch @@ -0,0 +1,35 @@ +From c2bbe774ce03661666a1f48922a9ab681ef4f64b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Sep 2021 11:08:41 +1200 +Subject: [PATCH] ldb_msg: Don't fail in ldb_msg_copy() if source DN is NULL + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +Reviewed-by: Douglas Bagnall +--- + lib/ldb/common/ldb_msg.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 0179c35659b..57dfc5a04c2 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -876,8 +876,10 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + msg2 = ldb_msg_copy_shallow(mem_ctx, msg); + if (msg2 == NULL) return NULL; + +- msg2->dn = ldb_dn_copy(msg2, msg2->dn); +- if (msg2->dn == NULL) goto failed; ++ if (msg2->dn != NULL) { ++ msg2->dn = ldb_dn_copy(msg2, msg2->dn); ++ if (msg2->dn == NULL) goto failed; ++ } + + for (i=0;inum_elements;i++) { + struct ldb_message_element *el = &msg2->elements[i]; +-- +2.25.1 + diff --git a/backport-0002-CVE-2022-2031-CVE-2022-32744.patch b/backport-0002-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..c1a44923da2db49fdd4f71ed8c202f4672f75db0 --- /dev/null +++ b/backport-0002-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,104 @@ +From 8048b6fe8cfd2887090a5aec682060b396794f6b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 8 Oct 2021 16:06:58 +1300 +Subject: [PATCH] s4:kdc: Simplify samba_kdc_update_pac_blob() to take + ldb_context as parameter + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 7149eeaceb426470b1b8181749d2d081c2fb83a4) +--- + source4/kdc/mit_samba.c | 7 +------ + source4/kdc/pac-glue.c | 5 ++--- + source4/kdc/pac-glue.h | 3 +-- + source4/kdc/wdc-samba4.c | 2 +- + 4 files changed, 5 insertions(+), 12 deletions(-) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 54dcd545ea1..2936fe2d18a 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -482,7 +482,6 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + DATA_BLOB *deleg_blob = NULL; + struct samba_kdc_entry *client_skdc_entry = NULL; + struct samba_kdc_entry *krbtgt_skdc_entry = NULL; +- struct samba_kdc_entry *server_skdc_entry = NULL; + bool is_in_db = false; + bool is_untrusted = false; + size_t num_types = 0; +@@ -513,9 +512,6 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + if (server == NULL) { + return EINVAL; + } +- server_skdc_entry = +- talloc_get_type_abort(server->e_data, +- struct samba_kdc_entry); + + if (krbtgt == NULL) { + return EINVAL; +@@ -575,8 +571,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + + nt_status = samba_kdc_update_pac_blob(tmp_ctx, + context, +- krbtgt_skdc_entry, +- server_skdc_entry, ++ krbtgt_skdc_entry->kdc_db_ctx->samdb, + *pac, + pac_blob, + pac_srv_sig, +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index 04fbc5cf487..88bcb734fc5 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -747,8 +747,7 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + + NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + krb5_context context, +- struct samba_kdc_entry *krbtgt, +- struct samba_kdc_entry *server, ++ struct ldb_context *samdb, + const krb5_pac pac, DATA_BLOB *pac_blob, + struct PAC_SIGNATURE_DATA *pac_srv_sig, + struct PAC_SIGNATURE_DATA *pac_kdc_sig) +@@ -768,7 +767,7 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + * as the token might be generated by a trusted domain. + */ + nt_status = authsam_update_user_info_dc(mem_ctx, +- krbtgt->kdc_db_ctx->samdb, ++ samdb, + user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 2eb7fd3b755..7b51b0389f5 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -51,8 +51,7 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + + NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + krb5_context context, +- struct samba_kdc_entry *krbtgt, +- struct samba_kdc_entry *server, ++ struct ldb_context *samdb, + const krb5_pac pac, DATA_BLOB *pac_blob, + struct PAC_SIGNATURE_DATA *pac_srv_sig, + struct PAC_SIGNATURE_DATA *pac_kdc_sig); +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index a7d8de1f417..68c8a8aa572 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -186,7 +186,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + } + + nt_status = samba_kdc_update_pac_blob(mem_ctx, context, +- krbtgt_skdc_entry, p, ++ krbtgt_skdc_entry->kdc_db_ctx->samdb, + *pac, pac_blob, + pac_srv_sig, pac_kdc_sig); + if (!NT_STATUS_IS_OK(nt_status)) { +-- +2.33.0 + diff --git a/backport-0002-CVE-2022-32746.patch b/backport-0002-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..ec6bd7e97021e574f82ef1b2646cdbd7d3fc5514 --- /dev/null +++ b/backport-0002-CVE-2022-32746.patch @@ -0,0 +1,25 @@ +From 5d958156c7e5d6c1da61d18fe4fd105b22639b56 Mon Sep 17 00:00:00 2001 +Subject: [PATCH 01/99] CVE-2022-32746 s4/dsdb/objectclass_attrs: Fix typo + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +index 6ab46a729a2..2a77353cdfc 100644 +--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c ++++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +@@ -263,7 +263,7 @@ static int attr_handler(struct oc_context *ac) + LDB_CONTROL_AS_SYSTEM_OID); + if (!dsdb_module_am_system(ac->module) && !as_system) { + ldb_asprintf_errstring(ldb, +- "objectclass_attrs: attribute '%s' on entry '%s' must can only be modified as system", ++ "objectclass_attrs: attribute '%s' on entry '%s' can only be modified as system", + msg->elements[i].name, + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; +-- +2.25.1 diff --git a/backport-0003-CVE-2022-2031-CVE-2022-32744.patch b/backport-0003-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..e0f37b2f10a88640bb3a27e56671404047498e7e --- /dev/null +++ b/backport-0003-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,359 @@ +From eadd3b8844d1e4162558f443e5cd4905f12667e6 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 8 Oct 2021 16:08:39 +1300 +Subject: [PATCH] s4:kdc: Check ticket signature + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 02fa69c6c73c01d82807be4370e838f3e7c66f35) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 270 ++++++++++++++++++++++++++------- + 2 files changed, 215 insertions(+), 64 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 037db40ce46..589df8a651d 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -23,7 +23,10 @@ + + #include "includes.h" + #include "kdc/kdc-glue.h" ++#include "kdc/db-glue.h" + #include "kdc/pac-glue.h" ++#include "sdb.h" ++#include "sdb_hdb.h" + + /* + * Given the right private pointer from hdb_samba4, +@@ -94,15 +97,13 @@ static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context + return samba_wdc_get_pac(priv, context, client, NULL, pac); + } + +-/* Resign (and reform, including possibly new groups) a PAC */ +- +-static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, +- const krb5_principal client_principal, +- const krb5_principal delegated_proxy_principal, +- struct hdb_entry_ex *client, +- struct hdb_entry_ex *server, +- struct hdb_entry_ex *krbtgt, +- krb5_pac *pac) ++static krb5_error_code samba_wdc_reget_pac2(krb5_context context, ++ const krb5_principal delegated_proxy_principal, ++ struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, ++ struct hdb_entry_ex *krbtgt, ++ krb5_pac *pac, ++ krb5_cksumtype ctype) + { + struct samba_kdc_entry *p = + talloc_get_type_abort(server->ctx, +@@ -110,15 +111,13 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + struct samba_kdc_entry *krbtgt_skdc_entry = + talloc_get_type_abort(krbtgt->ctx, + struct samba_kdc_entry); +- TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context"); ++ TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac2 context"); + krb5_pac new_pac = NULL; + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *deleg_blob = NULL; + krb5_error_code ret; + NTSTATUS nt_status; +- struct PAC_SIGNATURE_DATA *pac_srv_sig; +- struct PAC_SIGNATURE_DATA *pac_kdc_sig; + bool is_in_db, is_untrusted; + size_t num_types = 0; + uint32_t *types = NULL; +@@ -130,6 +129,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + ssize_t upn_dns_info_idx = -1; + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; ++ ssize_t tkt_checksum_idx = -1; + + if (!mem_ctx) { + return ENOMEM; +@@ -150,6 +150,71 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + return ret; + } + ++ if (delegated_proxy_principal != NULL) { ++ krb5_enctype etype; ++ Key *key = NULL; ++ ++ if (!is_in_db) { ++ /* ++ * The RODC-issued PAC was signed by a KDC entry that we ++ * don't have a key for. The server signature is not ++ * trustworthy, since it could have been created by the ++ * server we got the ticket from. We must not proceed as ++ * otherwise the ticket signature is unchecked. ++ */ ++ talloc_free(mem_ctx); ++ return HDB_ERR_NOT_FOUND_HERE; ++ } ++ ++ /* Fetch the correct key depending on the checksum type. */ ++ if (ctype == CKSUMTYPE_HMAC_MD5) { ++ etype = ENCTYPE_ARCFOUR_HMAC; ++ } else { ++ ret = krb5_cksumtype_to_enctype(context, ++ ctype, ++ &etype); ++ if (ret != 0) { ++ talloc_free(mem_ctx); ++ return ret; ++ } ++ } ++ ret = hdb_enctype2key(context, &krbtgt->entry, etype, &key); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* Check the KDC and ticket signatures. */ ++ ret = krb5_pac_verify(context, ++ *pac, ++ 0, ++ NULL, ++ NULL, ++ &key->key); ++ if (ret != 0) { ++ DEBUG(1, ("PAC KDC signature failed to verify\n")); ++ talloc_free(mem_ctx); ++ return ret; ++ } ++ ++ deleg_blob = talloc_zero(mem_ctx, DATA_BLOB); ++ if (!deleg_blob) { ++ talloc_free(mem_ctx); ++ return ENOMEM; ++ } ++ ++ nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, ++ context, *pac, ++ server->entry.principal, ++ delegated_proxy_principal, ++ deleg_blob); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ DEBUG(0, ("Building PAC failed: %s\n", ++ nt_errstr(nt_status))); ++ talloc_free(mem_ctx); ++ return EINVAL; ++ } ++ } ++ + if (is_untrusted) { + struct samba_kdc_entry *client_skdc_entry = NULL; + +@@ -173,52 +238,10 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + return ENOMEM; + } + +- pac_srv_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); +- if (!pac_srv_sig) { +- talloc_free(mem_ctx); +- return ENOMEM; +- } +- +- pac_kdc_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); +- if (!pac_kdc_sig) { +- talloc_free(mem_ctx); +- return ENOMEM; +- } +- + nt_status = samba_kdc_update_pac_blob(mem_ctx, context, + krbtgt_skdc_entry->kdc_db_ctx->samdb, + *pac, pac_blob, +- pac_srv_sig, pac_kdc_sig); +- if (!NT_STATUS_IS_OK(nt_status)) { +- DEBUG(0, ("Building PAC failed: %s\n", +- nt_errstr(nt_status))); +- talloc_free(mem_ctx); +- return EINVAL; +- } +- +- if (is_in_db) { +- /* Now check the KDC signature, fetching the correct key based on the enc type */ +- ret = kdc_check_pac(context, pac_srv_sig->signature, pac_kdc_sig, krbtgt); +- if (ret != 0) { +- DEBUG(1, ("PAC KDC signature failed to verify\n")); +- talloc_free(mem_ctx); +- return ret; +- } +- } +- } +- +- if (delegated_proxy_principal) { +- deleg_blob = talloc_zero(mem_ctx, DATA_BLOB); +- if (!deleg_blob) { +- talloc_free(mem_ctx); +- return ENOMEM; +- } +- +- nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, +- context, *pac, +- server->entry.principal, +- delegated_proxy_principal, +- deleg_blob); ++ NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Building PAC failed: %s\n", + nt_errstr(nt_status))); +@@ -308,6 +331,18 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + } + kdc_checksum_idx = i; + break; ++ case PAC_TYPE_TICKET_CHECKSUM: ++ if (tkt_checksum_idx != -1) { ++ DEBUG(1, ("ticket checksum type[%"PRIu32"] twice [%zd] and [%zu]: \n", ++ types[i], ++ tkt_checksum_idx, ++ i)); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return EINVAL; ++ } ++ tkt_checksum_idx = i; ++ break; + default: + continue; + } +@@ -471,6 +506,131 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, + return ret; + } + ++/* Resign (and reform, including possibly new groups) a PAC */ ++ ++static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, ++ const krb5_principal client_principal, ++ const krb5_principal delegated_proxy_principal, ++ struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, ++ struct hdb_entry_ex *krbtgt, ++ krb5_pac *pac) ++{ ++ struct samba_kdc_entry *krbtgt_skdc_entry = ++ talloc_get_type_abort(krbtgt->ctx, ++ struct samba_kdc_entry); ++ krb5_error_code ret; ++ krb5_cksumtype ctype = CKSUMTYPE_NONE; ++ struct hdb_entry_ex signing_krbtgt_hdb; ++ ++ if (delegated_proxy_principal) { ++ uint16_t rodc_id; ++ unsigned int my_krbtgt_number; ++ ++ /* ++ * We're using delegated_proxy_principal for the moment to ++ * indicate cases where the ticket was encrypted with the server ++ * key, and not a krbtgt key. This cannot be trusted, so we need ++ * to find a krbtgt key that signs the PAC in order to trust the ++ * ticket. ++ * ++ * The krbtgt passed in to this function refers to the krbtgt ++ * used to decrypt the ticket of the server requesting ++ * S4U2Proxy. ++ * ++ * When we implement service ticket renewal, we need to check ++ * the PAC, and this will need to be updated. ++ */ ++ ret = krb5_pac_get_kdc_checksum_info(context, ++ *pac, ++ &ctype, ++ &rodc_id); ++ if (ret != 0) { ++ DEBUG(1, ("Failed to get PAC checksum info\n")); ++ return ret; ++ } ++ ++ /* ++ * We need to check the KDC and ticket signatures, fetching the ++ * correct key based on the enctype. ++ */ ++ ++ my_krbtgt_number = krbtgt_skdc_entry->kdc_db_ctx->my_krbtgt_number; ++ ++ if (my_krbtgt_number != 0) { ++ /* ++ * If we are an RODC, and we are not the KDC that signed ++ * the evidence ticket, then we need to proxy the ++ * request. ++ */ ++ if (rodc_id != my_krbtgt_number) { ++ return HDB_ERR_NOT_FOUND_HERE; ++ } ++ } else { ++ /* ++ * If we are a DC, the ticket may have been signed by a ++ * different KDC than the one that issued the header ++ * ticket. ++ */ ++ if (rodc_id != krbtgt->entry.kvno >> 16) { ++ struct sdb_entry_ex signing_krbtgt_sdb; ++ ++ /* ++ * If we didn't sign the ticket, then return an ++ * error. ++ */ ++ if (rodc_id != 0) { ++ return KRB5KRB_AP_ERR_MODIFIED; ++ } ++ ++ /* ++ * Fetch our key from the database. To support ++ * key rollover, we're going to need to try ++ * multiple keys by trial and error. For now, ++ * krbtgt keys aren't assumed to change. ++ */ ++ ret = samba_kdc_fetch(context, ++ krbtgt_skdc_entry->kdc_db_ctx, ++ krbtgt->entry.principal, ++ SDB_F_GET_KRBTGT | SDB_F_CANON, ++ 0, ++ &signing_krbtgt_sdb); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ ret = sdb_entry_ex_to_hdb_entry_ex(context, ++ &signing_krbtgt_sdb, ++ &signing_krbtgt_hdb); ++ sdb_free_entry(&signing_krbtgt_sdb); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ /* ++ * Replace the krbtgt entry with our own entry ++ * for further processing. ++ */ ++ krbtgt = &signing_krbtgt_hdb; ++ } ++ } ++ } ++ ++ ret = samba_wdc_reget_pac2(context, ++ delegated_proxy_principal, ++ client, ++ server, ++ krbtgt, ++ pac, ++ ctype); ++ ++ if (krbtgt == &signing_krbtgt_hdb) { ++ hdb_free_entry(context, &signing_krbtgt_hdb); ++ } ++ ++ return ret; ++} ++ + static char *get_netbios_name(TALLOC_CTX *mem_ctx, HostAddresses *addrs) + { + char *nb_name = NULL; +-- +2.33.0 + diff --git a/backport-0003-CVE-2022-32746.patch b/backport-0003-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..723d5c4b50614920aeb3a8116b18e8b306a69958 --- /dev/null +++ b/backport-0003-CVE-2022-32746.patch @@ -0,0 +1,38 @@ +From a68553792a8512a2d266bbb86f064f78b5482a65 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:41:02 +1200 +Subject: [PATCH 03/99] CVE-2022-32746 s4/dsdb/partition: Fix LDB flags + comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(req_msg->elements[el_idx].flags & LDB_FLAG_MOD_MASK) != 0 + +which is true whenever any of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/partition.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c +index 2544a106d13..2d90ca5d1b3 100644 +--- a/source4/dsdb/samdb/ldb_modules/partition.c ++++ b/source4/dsdb/samdb/ldb_modules/partition.c +@@ -493,8 +493,8 @@ static int partition_copy_all_callback_action( + * them here too + */ + for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) { +- if (req_msg->elements[el_idx].flags & LDB_FLAG_MOD_DELETE +- || ((req_msg->elements[el_idx].flags & LDB_FLAG_MOD_REPLACE) && ++ if (LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_DELETE ++ || ((LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_REPLACE) && + req_msg->elements[el_idx].num_values == 0)) { + if (ldb_msg_find_element(modify_msg, + req_msg->elements[el_idx].name) != NULL) { +-- +2.25.1 diff --git a/backport-0004-CVE-2022-2031-CVE-2022-32744.patch b/backport-0004-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..657a080037dcea6bf014116dd37c299875d58d0c --- /dev/null +++ b/backport-0004-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,103 @@ +From 2149108966f4159a218a901c19bea3921d68fa1e Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 18 Oct 2021 16:00:45 +1300 +Subject: [PATCH] kdc: Correctly strip PAC, rather than error on + UF_NO_AUTH_DATA_REQUIRED for servers + +UF_NO_AUTH_DATA_REQUIRED on a server/service account should cause +the PAC to be stripped not to given an error if the PAC was still +present. + +Tested against Windows 2019 + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +(cherry picked from commit 031a8287642e3c4b9d0b7c6b51f3b1d79b227542) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 38 +++++++++++++++++++++++----------- + 2 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 589df8a651d..ac9d7d51733 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -105,13 +105,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + krb5_pac *pac, + krb5_cksumtype ctype) + { +- struct samba_kdc_entry *p = ++ struct samba_kdc_entry *server_skdc_entry = + talloc_get_type_abort(server->ctx, + struct samba_kdc_entry); + struct samba_kdc_entry *krbtgt_skdc_entry = + talloc_get_type_abort(krbtgt->ctx, + struct samba_kdc_entry); +- TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac2 context"); ++ TALLOC_CTX *mem_ctx = talloc_named(server_skdc_entry, ++ 0, ++ "samba_kdc_reget_pac2 context"); + krb5_pac new_pac = NULL; + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; +@@ -135,12 +137,6 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + return ENOMEM; + } + +- /* The user account may be set not to want the PAC */ +- if (!samba_princ_needs_pac(p)) { +- talloc_free(mem_ctx); +- return EINVAL; +- } +- + /* If the krbtgt was generated by an RODC, and we are not that + * RODC, then we need to regenerate the PAC - we can't trust + * it */ +@@ -373,12 +369,28 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + return EINVAL; + } + +- /* Build an updated PAC */ ++ /* ++ * The server account may be set not to want the PAC. ++ * ++ * While this is wasteful if the above cacluations were done ++ * and now thrown away, this is cleaner as we do any ticket ++ * signature checking etc always. ++ * ++ * UF_NO_AUTH_DATA_REQUIRED is the rare case and most of the ++ * time (eg not accepting a ticket from the RODC) we do not ++ * need to re-generate anything anyway. ++ */ ++ if (!samba_princ_needs_pac(server_skdc_entry)) { ++ ret = 0; ++ new_pac = NULL; ++ goto out; ++ } ++ ++ /* Otherwise build an updated PAC */ + ret = krb5_pac_init(context, &new_pac); + if (ret != 0) { +- SAFE_FREE(types); +- talloc_free(mem_ctx); +- return ret; ++ new_pac = NULL; ++ goto out; + } + + for (i = 0;;) { +@@ -496,6 +508,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + } + } + ++out: ++ + SAFE_FREE(types); + + /* We now replace the pac */ +-- +2.33.0 + diff --git a/backport-0004-CVE-2022-32746.patch b/backport-0004-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b22de5853b0f2a93b1e91fd9fd2b28eaecabc7f --- /dev/null +++ b/backport-0004-CVE-2022-32746.patch @@ -0,0 +1,37 @@ +From 582ac171364f0c28f54eaf4f21b5bfa7569b5233 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:49:51 +1200 +Subject: [PATCH 04/99] CVE-2022-32746 s4:torture: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/torture/drs/rpc/dssync.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source4/torture/drs/rpc/dssync.c b/source4/torture/drs/rpc/dssync.c +index cde9f78692b..ff7ce2d9074 100644 +--- a/source4/torture/drs/rpc/dssync.c ++++ b/source4/torture/drs/rpc/dssync.c +@@ -527,7 +527,9 @@ static bool test_analyse_objects(struct torture_context *tctx, + el = &new_msg->elements[idx]; + a = dsdb_attribute_by_lDAPDisplayName(ldap_schema, + el->name); +- if (!(el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE))) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + /* DRS only value */ + is_warning = false; + } else if (a->linkID & 1) { +-- +2.25.1 diff --git a/backport-0005-CVE-2022-2031-CVE-2022-32744.patch b/backport-0005-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..f509e4a6eab0c94d3523f86c68cc335470f0e64c --- /dev/null +++ b/backport-0005-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,604 @@ +From 30fb296a38a72fd91161c4f48be3a0472479f2ff Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 26 Oct 2021 20:41:31 +1300 +Subject: [PATCH] CVE-2020-25719 s4:kdc: Add KDC support for + PAC_ATTRIBUTES_INFO PAC buffer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +Conflict: remove selftest/knownfail_heimdal_kdc +source4/heimdal/kdc/kerberos5.c +source4/heimdal/kdc/krb5tgs.c +--- + source4/heimdal/kdc/kerberos5.c | 23 +++-- + source4/heimdal/kdc/krb5tgs.c | 2 +- + source4/heimdal/kdc/windc.c | 7 +- + source4/heimdal/kdc/windc_plugin.h | 2 + + source4/kdc/mit_samba.c | 7 +- + source4/kdc/pac-glue.c | 147 ++++++++++++++++++++++++++++- + source4/kdc/pac-glue.h | 10 +- + source4/kdc/wdc-samba4.c | 45 ++++++++- + 8 files changed, 223 insertions(+), 20 deletions(-) + +diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c +index 27d38ad..cb34c8f 100644 +--- a/source4/heimdal/kdc/kerberos5.c ++++ b/source4/heimdal/kdc/kerberos5.c +@@ -913,27 +913,30 @@ _kdc_check_addresses(krb5_context context, + */ + + static krb5_boolean +-send_pac_p(krb5_context context, KDC_REQ *req) ++send_pac_p(krb5_context context, KDC_REQ *req, krb5_boolean *pac_request) + { + krb5_error_code ret; + PA_PAC_REQUEST pacreq; + const PA_DATA *pa; + int i = 0; + ++ *pac_request = TRUE; ++ + pa = _kdc_find_padata(req, &i, KRB5_PADATA_PA_PAC_REQUEST); + if (pa == NULL) +- return TRUE; ++ return FALSE; + + ret = decode_PA_PAC_REQUEST(pa->padata_value.data, + pa->padata_value.length, + &pacreq, + NULL); + if (ret) +- return TRUE; ++ return FALSE; + i = pacreq.include_pac; + free_PA_PAC_REQUEST(&pacreq); +- if (i == 0) +- return FALSE; ++ if (i == 0) { ++ *pac_request = FALSE; ++ } + return TRUE; + } + +@@ -1709,11 +1712,17 @@ _kdc_as_rep(krb5_context context, + } + + /* Add the PAC */ +- if (send_pac_p(context, req)) { ++ { + krb5_pac p = NULL; + krb5_data data; ++ krb5_boolean sent_pac_request; ++ krb5_boolean pac_request; ++ ++ sent_pac_request = send_pac_p(context, req, &pac_request); + +- ret = _kdc_pac_generate(context, client, pk_reply_key, &p); ++ ret = _kdc_pac_generate(context, client, pk_reply_key, ++ sent_pac_request ? &pac_request : NULL, ++ &p); + if (ret) { + kdc_log(context, config, 0, "PAC generation failed for -- %s", + client_name); +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index 701c04c..56b4ebe 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -2015,7 +2015,7 @@ server_lookup: + if(rspac.data) { + krb5_pac p = NULL; + krb5_data_free(&rspac); +- ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p); ++ ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &p); + if (ret) { + kdc_log(context, config, 0, "PAC generation failed for -- %s", + tpn); +diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c +index fb1c8a6..01b5b88 100644 +--- a/source4/heimdal/kdc/windc.c ++++ b/source4/heimdal/kdc/windc.c +@@ -74,6 +74,7 @@ krb5_error_code + _kdc_pac_generate(krb5_context context, + hdb_entry_ex *client, + const krb5_keyblock *pk_reply_key, ++ const krb5_boolean *pac_request, + krb5_pac *pac) + { + *pac = NULL; +@@ -81,8 +82,10 @@ _kdc_pac_generate(krb5_context context, + return 0; + if (windcft->pac_pk_generate != NULL && pk_reply_key != NULL) + return (windcft->pac_pk_generate)(windcctx, context, +- client, pk_reply_key, pac); +- return (windcft->pac_generate)(windcctx, context, client, pac); ++ client, pk_reply_key, ++ pac_request, pac); ++ return (windcft->pac_generate)(windcctx, context, client, ++ pac_request, pac); + } + + krb5_error_code +diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h +index bf90826..8c83f1d 100644 +--- a/source4/heimdal/kdc/windc_plugin.h ++++ b/source4/heimdal/kdc/windc_plugin.h +@@ -54,12 +54,14 @@ struct hdb_entry_ex; + typedef krb5_error_code + (*krb5plugin_windc_pac_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ ++ const krb5_boolean *, /* pac_request */ + krb5_pac *); + + typedef krb5_error_code + (*krb5plugin_windc_pac_pk_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ + const krb5_keyblock *, /* pk_replykey */ ++ const krb5_boolean *, /* pac_request */ + krb5_pac *); + + typedef krb5_error_code +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 710b23c..f63d80e 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -439,7 +439,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + skdc_entry, + &logon_info_blob, + cred_ndr_ptr, +- &upn_dns_info_blob); ++ &upn_dns_info_blob, ++ NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return EINVAL; +@@ -463,6 +464,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + pcred_blob, + upn_dns_info_blob, + NULL, ++ NULL, + pac); + + talloc_free(tmp_ctx); +@@ -547,7 +549,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + client_skdc_entry, + &pac_blob, + NULL, +- &upn_blob); ++ &upn_blob, ++ NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; + goto done; +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index c7faab9..75bb3a5 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -121,6 +121,43 @@ NTSTATUS samba_get_upn_info_pac_blob(TALLOC_CTX *mem_ctx, + return NT_STATUS_OK; + } + ++static ++NTSTATUS samba_get_pac_attrs_blob(TALLOC_CTX *mem_ctx, ++ const krb5_boolean *pac_request, ++ DATA_BLOB *pac_attrs_data) ++{ ++ union PAC_INFO pac_attrs; ++ enum ndr_err_code ndr_err; ++ NTSTATUS nt_status; ++ ++ ZERO_STRUCT(pac_attrs); ++ ++ *pac_attrs_data = data_blob_null; ++ ++ /* Set the length of the flags in bits. */ ++ pac_attrs.attributes_info.flags_length = 2; ++ ++ if (pac_request == NULL) { ++ pac_attrs.attributes_info.flags ++ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY; ++ } else if (*pac_request) { ++ pac_attrs.attributes_info.flags ++ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED; ++ } ++ ++ ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs, ++ PAC_TYPE_ATTRIBUTES_INFO, ++ (ndr_push_flags_fn_t)ndr_push_PAC_INFO); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ nt_status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(1, ("PAC ATTRIBUTES_INFO (presig) push failed: %s\n", ++ nt_errstr(nt_status))); ++ return nt_status; ++ } ++ ++ return NT_STATUS_OK; ++} ++ + static + NTSTATUS samba_get_cred_info_ndr_blob(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg, +@@ -421,12 +458,14 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + const DATA_BLOB *logon_blob, + const DATA_BLOB *cred_blob, + const DATA_BLOB *upn_blob, ++ const DATA_BLOB *pac_attrs_blob, + const DATA_BLOB *deleg_blob, + krb5_pac *pac) + { + krb5_data logon_data; + krb5_data cred_data; + krb5_data upn_data; ++ krb5_data pac_attrs_data; + krb5_data deleg_data; + krb5_error_code ret; + #ifdef SAMBA4_USES_HEIMDAL +@@ -471,6 +510,19 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + } + } + ++ ZERO_STRUCT(pac_attrs_data); ++ if (pac_attrs_blob != NULL) { ++ ret = smb_krb5_copy_data_contents(&pac_attrs_data, ++ pac_attrs_blob->data, ++ pac_attrs_blob->length); ++ if (ret != 0) { ++ smb_krb5_free_data_contents(context, &logon_data); ++ smb_krb5_free_data_contents(context, &cred_data); ++ smb_krb5_free_data_contents(context, &upn_data); ++ return ret; ++ } ++ } ++ + ZERO_STRUCT(deleg_data); + if (deleg_blob != NULL) { + ret = smb_krb5_copy_data_contents(&deleg_data, +@@ -480,6 +532,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &logon_data); + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + return ret; + } + } +@@ -489,6 +542,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &logon_data); + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -496,8 +550,9 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &logon_data); + smb_krb5_free_data_contents(context, &logon_data); + if (ret != 0) { +- smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &cred_data); ++ smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -509,6 +564,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &cred_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -527,6 +583,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + &null_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -537,6 +594,18 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + PAC_TYPE_UPN_DNS_INFO, + &upn_data); + smb_krb5_free_data_contents(context, &upn_data); ++ if (ret != 0) { ++ smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &deleg_data); ++ return ret; ++ } ++ } ++ ++ if (pac_attrs_blob != NULL) { ++ ret = krb5_pac_add_buffer(context, *pac, ++ PAC_TYPE_ATTRIBUTES_INFO, ++ &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &deleg_data); + return ret; +@@ -570,6 +639,48 @@ bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry) + return true; + } + ++int samba_client_requested_pac(krb5_context context, ++ krb5_pac *pac, ++ TALLOC_CTX *mem_ctx, ++ bool *requested_pac) ++{ ++ enum ndr_err_code ndr_err; ++ krb5_data k5pac_attrs_in; ++ DATA_BLOB pac_attrs_in; ++ union PAC_INFO pac_attrs; ++ int ret; ++ ++ *requested_pac = true; ++ ++ ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_ATTRIBUTES_INFO, ++ &k5pac_attrs_in); ++ if (ret != 0) { ++ return ret == ENOENT ? 0 : ret; ++ } ++ ++ pac_attrs_in = data_blob_const(k5pac_attrs_in.data, ++ k5pac_attrs_in.length); ++ ++ ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs, ++ PAC_TYPE_ATTRIBUTES_INFO, ++ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); ++ smb_krb5_free_data_contents(context, &k5pac_attrs_in); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(0,("can't parse the PAC ATTRIBUTES_INFO: %s\n", nt_errstr(nt_status))); ++ return EINVAL; ++ } ++ ++ if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY ++ | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) { ++ *requested_pac = true; ++ } else { ++ *requested_pac = false; ++ } ++ ++ return 0; ++} ++ + /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */ + int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, + bool *is_in_db, +@@ -645,12 +756,15 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *p, + DATA_BLOB **_logon_info_blob, + DATA_BLOB **_cred_ndr_blob, +- DATA_BLOB **_upn_info_blob) ++ DATA_BLOB **_upn_info_blob, ++ DATA_BLOB **_pac_attrs_blob, ++ const krb5_boolean *pac_request) + { + struct auth_user_info_dc *user_info_dc; + DATA_BLOB *logon_blob = NULL; + DATA_BLOB *cred_blob = NULL; + DATA_BLOB *upn_blob = NULL; ++ DATA_BLOB *pac_attrs_blob = NULL; + NTSTATUS nt_status; + + *_logon_info_blob = NULL; +@@ -658,6 +772,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + *_cred_ndr_blob = NULL; + } + *_upn_info_blob = NULL; ++ if (_pac_attrs_blob != NULL) { ++ *_pac_attrs_blob = NULL; ++ } + + /* The user account may be set not to want the PAC */ + if ( ! samba_princ_needs_pac(p)) { +@@ -681,6 +798,13 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + return NT_STATUS_NO_MEMORY; + } + ++ if (_pac_attrs_blob != NULL) { ++ pac_attrs_blob = talloc_zero(mem_ctx, DATA_BLOB); ++ if (pac_attrs_blob == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } ++ + nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, + lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), + lpcfg_sam_name(p->kdc_db_ctx->lp_ctx), +@@ -725,12 +849,27 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + return nt_status; + } + ++ if (pac_attrs_blob != NULL) { ++ nt_status = samba_get_pac_attrs_blob(pac_attrs_blob, ++ pac_request, ++ pac_attrs_blob); ++ ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ DEBUG(0, ("Building PAC ATTRIBUTES failed: %s\n", ++ nt_errstr(nt_status))); ++ return nt_status; ++ } ++ } ++ + TALLOC_FREE(user_info_dc); + *_logon_info_blob = logon_blob; + if (_cred_ndr_blob != NULL) { + *_cred_ndr_blob = cred_blob; + } + *_upn_info_blob = upn_blob; ++ if (_pac_attrs_blob != NULL) { ++ *_pac_attrs_blob = pac_attrs_blob; ++ } + return NT_STATUS_OK; + } + +@@ -744,7 +883,9 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + nt_status = samba_kdc_get_pac_blobs(mem_ctx, p, + _logon_info_blob, + NULL, /* cred_blob */ +- &upn_blob); ++ &upn_blob, ++ NULL, ++ NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 7b51b03..64ea3d8 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -31,11 +31,17 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + const DATA_BLOB *logon_blob, + const DATA_BLOB *cred_blob, + const DATA_BLOB *upn_blob, ++ const DATA_BLOB *pac_attrs_blob, + const DATA_BLOB *deleg_blob, + krb5_pac *pac); + + bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry); + ++int samba_client_requested_pac(krb5_context context, ++ krb5_pac *pac, ++ TALLOC_CTX *mem_ctx, ++ bool *requested_pac); ++ + int samba_krbtgt_is_in_db(struct samba_kdc_entry *skdc_entry, + bool *is_in_db, + bool *is_untrusted); +@@ -44,7 +50,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *skdc_entry, + DATA_BLOB **_logon_info_blob, + DATA_BLOB **_cred_ndr_blob, +- DATA_BLOB **_upn_info_blob); ++ DATA_BLOB **_upn_info_blob, ++ DATA_BLOB **_pac_attrs_blob, ++ const krb5_boolean *pac_request); + NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *skdc_entry, + DATA_BLOB **_logon_info_blob); +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 318bf60..f7a9366 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -37,6 +37,7 @@ + static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + struct hdb_entry_ex *client, + const krb5_keyblock *pk_reply_key, ++ const krb5_boolean *pac_request, + krb5_pac *pac) + { + TALLOC_CTX *mem_ctx; +@@ -46,6 +47,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + DATA_BLOB _cred_blob = data_blob_null; + DATA_BLOB *cred_blob = NULL; + DATA_BLOB *upn_blob = NULL; ++ DATA_BLOB *pac_attrs_blob = NULL; + krb5_error_code ret; + NTSTATUS nt_status; + struct samba_kdc_entry *skdc_entry = +@@ -64,7 +66,9 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry, + &logon_blob, + cred_ndr_ptr, +- &upn_blob); ++ &upn_blob, ++ &pac_attrs_blob, ++ pac_request); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return EINVAL; +@@ -84,7 +88,8 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + } + + ret = samba_make_krb5_pac(context, logon_blob, cred_blob, +- upn_blob, NULL, pac); ++ upn_blob, pac_attrs_blob, ++ NULL, pac); + + talloc_free(mem_ctx); + return ret; +@@ -92,9 +97,10 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + + static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context, + struct hdb_entry_ex *client, ++ const krb5_boolean *pac_request, + krb5_pac *pac) + { +- return samba_wdc_get_pac(priv, context, client, NULL, pac); ++ return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac); + } + + static krb5_error_code samba_wdc_reget_pac2(krb5_context context, +@@ -132,6 +138,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; + ssize_t tkt_checksum_idx = -1; ++ ssize_t attrs_info_idx = -1; + + if (!mem_ctx) { + return ENOMEM; +@@ -222,7 +229,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + struct samba_kdc_entry); + + nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, +- &pac_blob, NULL, &upn_blob); ++ &pac_blob, NULL, &upn_blob, ++ NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return EINVAL; +@@ -339,6 +347,18 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + } + tkt_checksum_idx = i; + break; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (attrs_info_idx != -1) { ++ DEBUG(1, ("attributes info type[%"PRIu32"] twice [%zd] and [%zu]: \n", ++ types[i], ++ attrs_info_idx, ++ i)); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return EINVAL; ++ } ++ attrs_info_idx = i; ++ break; + default: + continue; + } +@@ -386,6 +406,20 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + ++ if (!server_skdc_entry->is_krbtgt) { ++ /* ++ * The client may have requested no PAC when obtaining the ++ * TGT. ++ */ ++ bool requested_pac; ++ ret = samba_client_requested_pac(context, pac, mem_ctx, ++ &requested_pac); ++ if (ret != 0 || !requested_pac) { ++ new_pac = NULL; ++ goto out; ++ } ++ } ++ + /* Otherwise build an updated PAC */ + ret = krb5_pac_init(context, &new_pac); + if (ret != 0) { +@@ -471,6 +505,9 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + */ + type_blob = data_blob_const(&zero_byte, 1); + break; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ /* just copy... */ ++ break; + default: + /* just copy... */ + break; +-- +2.27.0 + diff --git a/backport-0005-CVE-2022-32746.patch b/backport-0005-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..6bed0f360b168ce1d1f117fa23a68472932fc3ca --- /dev/null +++ b/backport-0005-CVE-2022-32746.patch @@ -0,0 +1,39 @@ +From 0526d27e9eddd9c2a54434cf0dcdb136a6c659e4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 15:22:47 +1200 +Subject: [PATCH 05/99] CVE-2022-32746 s4/dsdb/acl: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set, so we +would not successfully return if the element was a DELETE. Correct the +expression to what it was intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/acl.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c +index 21e83276bfd..8016a2d4bd0 100644 +--- a/source4/dsdb/samdb/ldb_modules/acl.c ++++ b/source4/dsdb/samdb/ldb_modules/acl.c +@@ -734,8 +734,9 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, + * If not add or replace (eg delete), + * return success + */ +- if ((el->flags +- & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } +-- +2.25.1 diff --git a/backport-0006-CVE-2022-2031-CVE-2022-32744.patch b/backport-0006-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..df14c74df42ef5fd3230f8b1282ffeeed314216d --- /dev/null +++ b/backport-0006-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,168 @@ +From 60a136bcc6c993f9462247332624be17bc6dd9bb Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 1 Oct 2021 12:25:30 +1300 +Subject: [PATCH] CVE-2020-25718 s4-rpc_server: Provide wrapper + samdb_confirm_rodc_allowed_to_repl_to() + +This shares the lookup of the tokenGroups attribute. + +There will be a new caller that does not want to do this step, +so this is a wrapper of samdb_confirm_rodc_allowed_to_repl_to_sid_list() +rather than part of it + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Joseph Sutton +--- + source4/rpc_server/common/sid_helper.c | 45 +++++++++++++++++++ + source4/rpc_server/drsuapi/getncchanges.c | 24 ++-------- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 30 ++----------- + 3 files changed, 51 insertions(+), 48 deletions(-) + +diff --git a/source4/rpc_server/common/sid_helper.c b/source4/rpc_server/common/sid_helper.c +index 99c5fc20d9d..78cb35d3fc1 100644 +--- a/source4/rpc_server/common/sid_helper.c ++++ b/source4/rpc_server/common/sid_helper.c +@@ -213,3 +213,48 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct + return WERR_DS_DRA_SECRETS_DENIED; + + } ++ ++/* ++ * This is a wrapper for the above that pulls in the tokenGroups ++ * rather than relying on the caller providing those ++ */ ++WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, ++ struct ldb_message *rodc_msg, ++ struct ldb_message *obj_msg) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ WERROR werr; ++ uint32_t num_token_sids; ++ struct dom_sid *token_sids; ++ const struct dom_sid *object_sid = NULL; ++ ++ object_sid = samdb_result_dom_sid(frame, ++ obj_msg, ++ "objectSid"); ++ if (object_sid == NULL) { ++ return WERR_DS_DRA_BAD_DN; ++ } ++ ++ /* ++ * The SID list needs to include itself as well as the tokenGroups. ++ * ++ * TODO determine if sIDHistory is required for this check ++ */ ++ werr = samdb_result_sid_array_ndr(sam_ctx, ++ obj_msg, ++ frame, "tokenGroups", ++ &num_token_sids, ++ &token_sids, ++ object_sid, 1); ++ if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { ++ return WERR_DS_DRA_SECRETS_DENIED; ++ } ++ ++ werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, ++ rodc_msg, ++ obj_msg, ++ num_token_sids, ++ token_sids); ++ TALLOC_FREE(frame); ++ return werr; ++} +diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c +index 2fbd178cedc..11a6c93d4cd 100644 +--- a/source4/rpc_server/drsuapi/getncchanges.c ++++ b/source4/rpc_server/drsuapi/getncchanges.c +@@ -1176,8 +1176,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, + NULL }; + const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; + struct ldb_result *rodc_res = NULL, *obj_res = NULL; +- uint32_t num_token_sids; +- struct dom_sid *token_sids; + const struct dom_sid *object_sid = NULL; + WERROR werr; + +@@ -1287,25 +1285,9 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, + goto allowed; + } + +- /* +- * The SID list needs to include itself as well as the tokenGroups. +- * +- * TODO determine if sIDHistory is required for this check +- */ +- werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0], +- mem_ctx, "tokenGroups", +- &num_token_sids, +- &token_sids, +- object_sid, 1); +- if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { +- goto denied; +- } +- +- werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(b_state->sam_ctx_system, +- rodc_res->msgs[0], +- obj_res->msgs[0], +- num_token_sids, +- token_sids); ++ werr = samdb_confirm_rodc_allowed_to_repl_to(b_state->sam_ctx_system, ++ rodc_res->msgs[0], ++ obj_res->msgs[0]); + + if (W_ERROR_IS_OK(werr)) { + goto allowed; +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index bb3f83f435a..b3f06cfd505 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -2858,9 +2858,6 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, + int ret; + struct ldb_result *rodc_res = NULL, *obj_res = NULL; + WERROR werr; +- struct dom_sid *object_sid; +- uint32_t num_token_sids; +- struct dom_sid *token_sids; + + rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "", + dom_sid_string(mem_ctx, user_sid)); +@@ -2874,30 +2871,9 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, + ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0); + if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied; + +- object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); +- if (object_sid == NULL) { +- goto denied; +- } +- +- /* +- * The SID list needs to include itself as well as the tokenGroups. +- * +- * TODO determine if sIDHistory is required for this check +- */ +- werr = samdb_result_sid_array_ndr(sam_ctx, obj_res->msgs[0], +- mem_ctx, "tokenGroups", +- &num_token_sids, +- &token_sids, +- object_sid, 1); +- if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { +- goto denied; +- } +- +- werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, +- rodc_res->msgs[0], +- obj_res->msgs[0], +- num_token_sids, +- token_sids); ++ werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx, ++ rodc_res->msgs[0], ++ obj_res->msgs[0]); + + if (W_ERROR_IS_OK(werr)) { + goto allowed; +-- +2.33.0 + diff --git a/backport-0006-CVE-2022-32746.patch b/backport-0006-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b2cd012c5c11bf4baff8435c49217292fa35461 --- /dev/null +++ b/backport-0006-CVE-2022-32746.patch @@ -0,0 +1,30 @@ +From 2869b5aa3148869edf0d079266542aef6e64608e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:43:52 +1300 +Subject: [PATCH 06/99] CVE-2022-32746 ldb:rdn_name: Use LDB_FLAG_MOD_TYPE() + for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/modules/rdn_name.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c +index e69ad9315ae..25cffe07591 100644 +--- a/lib/ldb/modules/rdn_name.c ++++ b/lib/ldb/modules/rdn_name.c +@@ -545,7 +545,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (e != NULL) { + ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_linearized(req->op.mod.message->dn)); +- if (e->flags == LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(e->flags) == LDB_FLAG_MOD_REPLACE) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; +-- +2.25.1 diff --git a/backport-0007-CVE-2022-2031-CVE-2022-32744.patch b/backport-0007-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..606b65f7fe9b2c4a0c424f56b8f2084fc70fe600 --- /dev/null +++ b/backport-0007-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,94 @@ +From 36a1c87654cf011a597901d43a16dfbc0fecf330 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 9 Aug 2021 17:19:45 +0200 +Subject: [PATCH] CVE-2020-25719 s4:kdc: Add samba_kdc_validate_pac_blob() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +--- + source4/kdc/pac-glue.c | 56 ++++++++++++++++++++++++++++++++++++++++++ + source4/kdc/pac-glue.h | 5 ++++ + 2 files changed, 61 insertions(+) + +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index 4066389e717..8a3ec22190c 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -918,3 +918,59 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, + talloc_free(tmp_ctx); + return nt_status; + } ++ ++/* Does a parse and SID check, but no crypto. */ ++krb5_error_code samba_kdc_validate_pac_blob( ++ krb5_context context, ++ struct samba_kdc_entry *client_skdc_entry, ++ const krb5_pac pac) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct auth_user_info_dc *pac_user_info = NULL; ++ struct dom_sid *client_sid = NULL; ++ struct dom_sid pac_sid; ++ krb5_error_code code; ++ bool ok; ++ ++ code = kerberos_pac_to_user_info_dc(frame, ++ pac, ++ context, ++ &pac_user_info, ++ NULL, ++ NULL); ++ if (code != 0) { ++ goto out; ++ } ++ ++ if (pac_user_info->num_sids == 0) { ++ code = EINVAL; ++ goto out; ++ } ++ ++ pac_sid = pac_user_info->sids[0]; ++ client_sid = samdb_result_dom_sid(frame, ++ client_skdc_entry->msg, ++ "objectSid"); ++ ++ ok = dom_sid_equal(&pac_sid, client_sid); ++ if (!ok) { ++ struct dom_sid_buf buf1; ++ struct dom_sid_buf buf2; ++ ++ DBG_ERR("SID mismatch between PAC and looked up client: " ++ "PAC[%s] != CLI[%s]\n", ++ dom_sid_str_buf(&pac_sid, &buf1), ++ dom_sid_str_buf(client_sid, &buf2)); ++#if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */ ++ code = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; ++#else /* Heimdal (where this is an enum) */ ++ code = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; ++#endif ++ goto out; ++ } ++ ++ code = 0; ++out: ++ TALLOC_FREE(frame); ++ return code; ++} +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 7b51b0389f5..e83446647b3 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -69,3 +69,8 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, + const char *client_name, + const char *workstation, + bool password_change); ++ ++krb5_error_code samba_kdc_validate_pac_blob( ++ krb5_context context, ++ struct samba_kdc_entry *client_skdc_entry, ++ const krb5_pac pac); +-- +2.33.0 + diff --git a/backport-0007-CVE-2022-32746.patch b/backport-0007-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b346650b353ba77e7b613888880109085746254 --- /dev/null +++ b/backport-0007-CVE-2022-32746.patch @@ -0,0 +1,53 @@ +From 535b5a366a2ad054f729e57e282e402cf13b2efc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 19:49:19 +1200 +Subject: [PATCH 07/99] CVE-2022-32746 s4/dsdb/repl_meta_data: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index ab506cec488..29ffda75c87 100644 +--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3525,7 +3525,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_REPLACE) { + return ldb_module_operr(module); + } + +@@ -3558,11 +3558,11 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_DELETE) { + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[1].flags) != LDB_FLAG_MOD_ADD) { + return ldb_module_operr(module); + } + +@@ -3645,7 +3645,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[0].flags) != LDB_FLAG_MOD_ADD) { + talloc_free(ac); + return ldb_module_operr(module); + } +-- +2.25.1 diff --git a/backport-0008-CVE-2022-2031-CVE-2022-32744.patch b/backport-0008-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..5baeceb50ed52be4faf0d649c5a91b6c96ebee35 --- /dev/null +++ b/backport-0008-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,64 @@ +From 5cdec75f8bceee0e4996682d09104ff076e241b3 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 18 Oct 2021 15:21:50 +1300 +Subject: [PATCH] kdc: Remove UF_NO_AUTH_DATA_REQUIRED from client principals + +Tests against Windows 2019 show that UF_NO_AUTH_DATA_REQUIRED +applies to services only, not to clients. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14871 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Stefan Metzmacher +[abartlet@samba.org backported from commit 92e8ce18a79e88c9b961dc20e39436c4cf653013 + as there was a knownfail conflict with the test_remove_pac case + which succeeds on this branch] +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/mit_samba.c | 7 ------- + source4/kdc/pac-glue.c | 5 ----- + 2 files changed, 12 deletions(-) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 1f061f0..f713581 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -512,18 +512,11 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; + krb5_pac new_pac = NULL; +- bool ok; + + if (client != NULL) { + client_skdc_entry = + talloc_get_type_abort(client->e_data, + struct samba_kdc_entry); +- +- /* The user account may be set not to want the PAC */ +- ok = samba_princ_needs_pac(client_skdc_entry); +- if (!ok) { +- return EINVAL; +- } + } + + if (server == NULL) { +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index 6c63147..5ad4bbb 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -783,11 +783,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + *_pac_attrs_blob = NULL; + } + +- /* The user account may be set not to want the PAC */ +- if ( ! samba_princ_needs_pac(p)) { +- return NT_STATUS_OK; +- } +- + logon_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (logon_blob == NULL) { + return NT_STATUS_NO_MEMORY; +-- +2.27.0 + diff --git a/backport-0008-CVE-2022-32746.patch b/backport-0008-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..82e1cf08e96e0d1da2036fd134622b5192801f39 --- /dev/null +++ b/backport-0008-CVE-2022-32746.patch @@ -0,0 +1,39 @@ +From bedd0b768c3f92645af033399aefd7ee971d9150 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:11:33 +1200 +Subject: [PATCH 08/99] CVE-2022-32746 s4/dsdb/tombstone_reanimate: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 64e05195798..5f8911c66be 100644 +--- a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -104,7 +104,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + if (el_dn == NULL) { + return false; + } +- if (el_dn->flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(el_dn->flags) != LDB_FLAG_MOD_REPLACE) { + return false; + } + if (el_dn->num_values != 1) { +@@ -117,7 +117,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + return false; + } + +- if (el_deleted->flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(el_deleted->flags) != LDB_FLAG_MOD_DELETE) { + return false; + } + +-- +2.25.1 diff --git a/backport-0009-CVE-2022-2031-CVE-2022-32744.patch b/backport-0009-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..f5ea2f3918c68ceb24abde4f00cb4aaebc5d8327 --- /dev/null +++ b/backport-0009-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,57 @@ +From 048c400e02c5fef623ed95dfdd92bc1591ef6710 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 9 Aug 2021 17:22:52 +0200 +Subject: [PATCH] CVE-2020-25719 mit_samba: The samba_princ_needs_pac check + should be on the server entry + +This does the same check as the hdb plugin now. The client check is already +done earlier. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +--- + source4/kdc/mit_samba.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index be6ea83c042..d11e1640ee9 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -486,6 +486,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + DATA_BLOB *deleg_blob = NULL; + struct samba_kdc_entry *client_skdc_entry = NULL; + struct samba_kdc_entry *krbtgt_skdc_entry = NULL; ++ struct samba_kdc_entry *server_skdc_entry = NULL; + bool is_in_db = false; + bool is_untrusted = false; + size_t num_types = 0; +@@ -499,6 +500,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; + krb5_pac new_pac = NULL; ++ bool ok; + + if (client != NULL) { + client_skdc_entry = +@@ -510,6 +512,16 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + return EINVAL; + } + ++ server_skdc_entry = ++ talloc_get_type_abort(server->e_data, ++ struct samba_kdc_entry); ++ ++ /* The account may be set not to want the PAC */ ++ ok = samba_princ_needs_pac(server_skdc_entry); ++ if (!ok) { ++ return EINVAL; ++ } ++ + if (krbtgt == NULL) { + return EINVAL; + } +-- +2.33.0 + diff --git a/backport-0009-CVE-2022-32746.patch b/backport-0009-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..d5ebb6f6eb72fbbb0705b7a565d31758528aa2d8 --- /dev/null +++ b/backport-0009-CVE-2022-32746.patch @@ -0,0 +1,30 @@ +From 49dd9042f4ee380fa1dafcebcb54d0e1f0852463 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:12:39 +1200 +Subject: [PATCH 09/99] CVE-2022-32746 s4/registry: Use LDB_FLAG_MOD_TYPE() for + flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/lib/registry/ldb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/lib/registry/ldb.c b/source4/lib/registry/ldb.c +index e089355975b..db383a560da 100644 +--- a/source4/lib/registry/ldb.c ++++ b/source4/lib/registry/ldb.c +@@ -859,7 +859,7 @@ static WERROR ldb_set_value(struct hive_key *parent, + + /* Try first a "modify" and if this doesn't work do try an "add" */ + for (i = 0; i < msg->num_elements; i++) { +- if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) { + msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + } +-- +2.25.1 diff --git a/backport-0010-CVE-2022-2031-CVE-2022-32744.patch b/backport-0010-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..d2fb75935bfc4ccb8eb5daff64d5f142b72bdb36 --- /dev/null +++ b/backport-0010-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,69 @@ +From 1fcd10069f774758c8234818ebe81b7ee5966d1d Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 9 Aug 2021 17:25:53 +0200 +Subject: [PATCH] CVE-2020-25719 mit_samba: Create the talloc context earlier + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +--- + source4/kdc/mit_samba.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index d11e1640ee9..d0e68ec8ea4 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -502,6 +502,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + krb5_pac new_pac = NULL; + bool ok; + ++ /* Create a memory context early so code can use talloc_stackframe() */ ++ tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ + if (client != NULL) { + client_skdc_entry = + talloc_get_type_abort(client->e_data, +@@ -509,7 +515,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + + if (server == NULL) { +- return EINVAL; ++ code = EINVAL; ++ goto done; + } + + server_skdc_entry = +@@ -519,21 +526,18 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + /* The account may be set not to want the PAC */ + ok = samba_princ_needs_pac(server_skdc_entry); + if (!ok) { +- return EINVAL; ++ code = EINVAL; ++ goto done; + } + + if (krbtgt == NULL) { +- return EINVAL; ++ code = EINVAL; ++ goto done; + } + krbtgt_skdc_entry = + talloc_get_type_abort(krbtgt->e_data, + struct samba_kdc_entry); + +- tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); +- if (tmp_ctx == NULL) { +- return ENOMEM; +- } +- + code = samba_krbtgt_is_in_db(krbtgt_skdc_entry, + &is_in_db, + &is_untrusted); +-- +2.33.0 + diff --git a/backport-0010-CVE-2022-32746.patch b/backport-0010-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..62573e3f0df2c3aeb2232816d5c59f7379873007 --- /dev/null +++ b/backport-0010-CVE-2022-32746.patch @@ -0,0 +1,114 @@ +From faa61ab3053d077ac9d0aa67e955217e85b660f4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:10:32 +1300 +Subject: [PATCH 10/99] CVE-2022-32746 ldb: Add flag to mark message element + values as shared + +When making a shallow copy of an ldb message, mark the message elements +of the copy as sharing their values with the message elements in the +original message. + +This flag value will be heeded in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 43 +++++++++++++++++++++++++++++++----- + lib/ldb/include/ldb_module.h | 6 +++++ + 2 files changed, 43 insertions(+), 6 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 57dfc5a04c2..2a9ce384bb9 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -833,11 +833,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg) + ldb_msg_element_compare_name); + } + +-/* +- shallow copy a message - copying only the elements array so that the caller +- can safely add new elements without changing the message +-*/ +-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) + { + struct ldb_message *msg2; +@@ -863,6 +859,35 @@ failed: + return NULL; + } + ++/* ++ shallow copy a message - copying only the elements array so that the caller ++ can safely add new elements without changing the message ++*/ ++struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++ const struct ldb_message *msg) ++{ ++ struct ldb_message *msg2; ++ unsigned int i; ++ ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); ++ if (msg2 == NULL) { ++ return NULL; ++ } ++ ++ for (i = 0; i < msg2->num_elements; ++i) { ++ /* ++ * Mark this message's elements as sharing their values with the ++ * original message, so that we don't inadvertently modify or ++ * free them. We don't mark the original message element as ++ * shared, so the original message element should not be ++ * modified or freed while the shallow copy lives. ++ */ ++ struct ldb_message_element *el = &msg2->elements[i]; ++ el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES; ++ } ++ ++ return msg2; ++} + + /* + copy a message, allocating new memory for all parts +@@ -873,7 +898,7 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + struct ldb_message *msg2; + unsigned int i, j; + +- msg2 = ldb_msg_copy_shallow(mem_ctx, msg); ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); + if (msg2 == NULL) return NULL; + + if (msg2->dn != NULL) { +@@ -894,6 +919,12 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + goto failed; + } + } ++ ++ /* ++ * Since we copied this element's values, we can mark them as ++ * not shared. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; + } + + return msg2; +diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h +index 8c1e5ee7936..4c7c85a17f0 100644 +--- a/lib/ldb/include/ldb_module.h ++++ b/lib/ldb/include/ldb_module.h +@@ -96,6 +96,12 @@ struct ldb_module; + */ + #define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100 + ++/* ++ * indicates that this element's values are shared with another element (for ++ * example, in a shallow copy of an ldb_message) and should not be freed ++ */ ++#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200 ++ + /* an extended match rule that always fails to match */ + #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1" + +-- +2.25.1 diff --git a/backport-0011-CVE-2022-2031-CVE-2022-32744.patch b/backport-0011-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb2197649d8b3c587e8188ef6d6b384108189ccd --- /dev/null +++ b/backport-0011-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,67 @@ +From d15ace2d81783a92474e2dbe6c02f20589aa70f0 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Mon, 9 Aug 2021 17:20:31 +0200 +Subject: [PATCH] CVE-2020-25719 s4:kdc: Check if the pac is valid before + updating it + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Andreas Schneider +Reviewed-by: Andrew Bartlett +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/mit_samba.c | 9 +++++++++ + source4/kdc/wdc-samba4.c | 17 +++++++++++++++++ + 4 files changed, 32 insertions(+), 35 deletions(-) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index d0e68ec8ea4..592f6a3bac4 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -512,6 +512,15 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + client_skdc_entry = + talloc_get_type_abort(client->e_data, + struct samba_kdc_entry); ++ ++ /* ++ * Check the objectSID of the client and pac data are the same. ++ * Does a parse and SID check, but no crypto. ++ */ ++ code = samba_kdc_validate_pac_blob(context, client_skdc_entry, *pac); ++ if (code != 0) { ++ goto done; ++ } + } + + if (server == NULL) { +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index ac9d7d51733..ed6e9fb9b63 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -137,6 +137,23 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + return ENOMEM; + } + ++ if (client != NULL) { ++ struct samba_kdc_entry *client_skdc_entry = NULL; ++ ++ client_skdc_entry = talloc_get_type_abort(client->ctx, ++ struct samba_kdc_entry); ++ ++ /* ++ * Check the objectSID of the client and pac data are the same. ++ * Does a parse and SID check, but no crypto. ++ */ ++ ret = samba_kdc_validate_pac_blob(context, client_skdc_entry, *pac); ++ if (ret != 0) { ++ talloc_free(mem_ctx); ++ return ret; ++ } ++ } ++ + /* If the krbtgt was generated by an RODC, and we are not that + * RODC, then we need to regenerate the PAC - we can't trust + * it */ +-- +2.33.0 + diff --git a/backport-0011-CVE-2022-32746.patch b/backport-0011-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a70d2549fdd0d1cb04f7f18425b2a0fa3679605 --- /dev/null +++ b/backport-0011-CVE-2022-32746.patch @@ -0,0 +1,180 @@ +From 4e5fb78c3dcff60aa8fd4b07dad4660bbb30532b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:35:13 +1300 +Subject: [PATCH 11/99] CVE-2022-32746 ldb: Ensure shallow copy modifications + do not affect original message + +Using the newly added ldb flag, we can now detect when a message has +been shallow-copied so that its elements share their values with the +original message elements. Then when adding values to the copied +message, we now make a copy of the shared values array first. + +This should prevent a use-after-free that occurred in LDB modules when +new values were added to a shallow copy of a message by calling +talloc_realloc() on the original values array, invalidating the 'values' +pointer in the original message element. The original values pointer can +later be used in the database audit logging module which logs database +requests, and potentially cause a crash. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 52 ++++++++++++++++++++++++++++++++------ + lib/ldb/include/ldb.h | 6 +++++ + source4/dsdb/common/util.c | 20 +++++---------- + 3 files changed, 56 insertions(+), 22 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 2a9ce384bb9..44d3b29e9a7 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -417,6 +417,47 @@ int ldb_msg_add(struct ldb_message *msg, + return LDB_SUCCESS; + } + ++/* ++ * add a value to a message element ++ */ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val) ++{ ++ struct ldb_val *vals; ++ ++ if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) { ++ /* ++ * Another message is using this message element's values array, ++ * so we don't want to make any modifications to the original ++ * message, or potentially invalidate its own values by calling ++ * talloc_realloc(). Make a copy instead. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; ++ ++ vals = talloc_array(mem_ctx, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ if (el->values != NULL) { ++ memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val)); ++ } ++ } else { ++ vals = talloc_realloc(mem_ctx, el->values, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ } ++ el->values = vals; ++ el->values[el->num_values] = *val; ++ el->num_values++; ++ ++ return LDB_SUCCESS; ++} ++ + /* + add a value to a message + */ +@@ -426,7 +467,6 @@ int ldb_msg_add_value(struct ldb_message *msg, + struct ldb_message_element **return_el) + { + struct ldb_message_element *el; +- struct ldb_val *vals; + int ret; + + el = ldb_msg_find_element(msg, attr_name); +@@ -437,14 +477,10 @@ int ldb_msg_add_value(struct ldb_message *msg, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values+1); +- if (!vals) { +- return LDB_ERR_OPERATIONS_ERROR; ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; + } +- el->values = vals; +- el->values[el->num_values] = *val; +- el->num_values++; + + if (return_el) { + *return_el = el; +diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h +index bc44157eaf4..129beefeaf5 100644 +--- a/lib/ldb/include/ldb.h ++++ b/lib/ldb/include/ldb.h +@@ -1981,6 +1981,12 @@ int ldb_msg_add_empty(struct ldb_message *msg, + int flags, + struct ldb_message_element **return_el); + ++/** ++ add a value to a message element ++*/ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val); + /** + add a element to a ldb_message + */ +diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c +index 5ce4c0a5e33..577b2a33873 100644 +--- a/source4/dsdb/common/util.c ++++ b/source4/dsdb/common/util.c +@@ -816,7 +816,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -851,14 +851,10 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +@@ -872,7 +868,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -907,14 +903,10 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +-- +2.25.1 diff --git a/backport-0012-CVE-2022-2031-CVE-2022-32744.patch b/backport-0012-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ef0bc7cc31cc6bd1db504f531712d5bf4f8e9c0 --- /dev/null +++ b/backport-0012-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,101 @@ +From d3bd072c0e9b3810921048663ac59a8f70739b31 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 1 Oct 2021 15:59:28 +1300 +Subject: [PATCH] CVE-2020-25718 dsdb: Bring sid_helper.c into common code as + rodc_helper.c + +These common routines will assist the KDC to do the same access +checking as the RPC servers need to do regarding which accounts +a RODC can act with regard to. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Joseph Sutton +--- + .../common/sid_helper.c => dsdb/common/rodc_helper.c} | 1 - + source4/dsdb/wscript_build | 2 +- + source4/rpc_server/drsuapi/getncchanges.c | 1 - + source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 - + source4/rpc_server/wscript_build | 9 +-------- + 5 files changed, 2 insertions(+), 12 deletions(-) + rename source4/{rpc_server/common/sid_helper.c => dsdb/common/rodc_helper.c} (99%) + +diff --git a/source4/rpc_server/common/sid_helper.c b/source4/dsdb/common/rodc_helper.c +similarity index 99% +rename from source4/rpc_server/common/sid_helper.c +rename to source4/dsdb/common/rodc_helper.c +index 78cb35d..3a9636a 100644 +--- a/source4/rpc_server/common/sid_helper.c ++++ b/source4/dsdb/common/rodc_helper.c +@@ -23,7 +23,6 @@ + #include "rpc_server/dcerpc_server.h" + #include "librpc/gen_ndr/ndr_security.h" + #include "source4/dsdb/samdb/samdb.h" +-#include "rpc_server/common/sid_helper.h" + #include "libcli/security/security.h" + + /* +diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build +index dbe5885..9836466 100644 +--- a/source4/dsdb/wscript_build ++++ b/source4/dsdb/wscript_build +@@ -13,7 +13,7 @@ bld.SAMBA_LIBRARY('samdb', + ) + + bld.SAMBA_LIBRARY('samdb-common', +- source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c', ++ source='common/util.c common/util_trusts.c common/util_groups.c common/util_samr.c common/dsdb_dn.c common/dsdb_access.c common/util_links.c common/rodc_helper.c', + autoproto='common/proto.h', + private_library=True, + deps='ldb NDR_DRSBLOBS util_ldb LIBCLI_AUTH samba-hostconfig samba_socket cli-ldap-common flag_mapping UTIL_RUNCMD' +diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c +index 603e41c..0d36a94 100644 +--- a/source4/rpc_server/drsuapi/getncchanges.c ++++ b/source4/rpc_server/drsuapi/getncchanges.c +@@ -32,7 +32,6 @@ + #include "libcli/security/session.h" + #include "rpc_server/drsuapi/dcesrv_drsuapi.h" + #include "rpc_server/dcerpc_server_proto.h" +-#include "rpc_server/common/sid_helper.h" + #include "../libcli/drsuapi/drsuapi.h" + #include "lib/util/binsearch.h" + #include "lib/util/tsort.h" +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index e307606..11e8280 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -43,7 +43,6 @@ + #include "librpc/gen_ndr/ndr_winbind.h" + #include "librpc/gen_ndr/ndr_winbind_c.h" + #include "lib/socket/netif.h" +-#include "rpc_server/common/sid_helper.h" + #include "lib/util/util_str_escape.h" + + #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \ +diff --git a/source4/rpc_server/wscript_build b/source4/rpc_server/wscript_build +index a7459d6..1c741d2 100644 +--- a/source4/rpc_server/wscript_build ++++ b/source4/rpc_server/wscript_build +@@ -7,17 +7,10 @@ bld.SAMBA_SUBSYSTEM('DCERPC_SHARE', + enabled=bld.CONFIG_SET('WITH_NTVFS_FILESERVER'), + ) + +-bld.SAMBA_SUBSYSTEM('DCERPC_SID_HELPER', +- source='common/sid_helper.c', +- autoproto='common/sid_helper.h', +- deps='ldb', +- enabled=bld.AD_DC_BUILD_IS_ENABLED(), +- ) +- + bld.SAMBA_SUBSYSTEM('DCERPC_COMMON', + source='common/server_info.c common/forward.c common/loadparm.c', + autoproto='common/proto.h', +- deps='ldb DCERPC_SHARE DCERPC_SID_HELPER', ++ deps='ldb DCERPC_SHARE', + enabled=bld.AD_DC_BUILD_IS_ENABLED() + ) + +-- +2.27.0 + diff --git a/backport-0012-CVE-2022-32746.patch b/backport-0012-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..2843a6e97476f2f660516044877277d0076b19fa --- /dev/null +++ b/backport-0012-CVE-2022-32746.patch @@ -0,0 +1,276 @@ +From 512a2617b1593bdc16caeeeda4312a581cbb34e9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 16:30:03 +1300 +Subject: [PATCH 12/99] CVE-2022-32746 ldb: Add functions for appending to an + ldb_message + +Currently, there are many places where we use ldb_msg_add_empty() to add +an empty element to a message, and then call ldb_msg_add_value() or +similar to add values to that element. However, this performs an +unnecessary search of the message's elements to locate the new element. +Moreover, if an element with the same attribute name already exists +earlier in the message, the values will be added to that element, +instead of to the intended newly added element. + +A similar pattern exists where we add values to a message, and then call +ldb_msg_find_element() to locate that message element and sets its flags +to (e.g.) LDB_FLAG_MOD_REPLACE. This also performs an unnecessary +search, and may locate the wrong message element for setting the flags. + +To avoid these problems, add functions for appending a value to a +message, so that a particular value can be added to the end of a message +in a single operation. + +For ADD requests, it is important that no two message elements share the +same attribute name, otherwise things will break. (Normally, +ldb_msg_normalize() is called before processing the request to help +ensure this.) Thus, we must be careful not to append an attribute to an +ADD message, unless we are sure (e.g. through ldb_msg_find_element()) +that an existing element for that attribute is not present. + +These functions will be used in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++- + lib/ldb/include/ldb.h | 24 ++++++ + 2 files changed, 185 insertions(+), 4 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 44d3b29e9a7..9cd7998e21c 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -509,12 +509,15 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + + + /* +- add a string element to a message ++ add a string element to a message, specifying flags + */ +-int ldb_msg_add_string(struct ldb_message *msg, +- const char *attr_name, const char *str) ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags) + { + struct ldb_val val; ++ int ret; ++ struct ldb_message_element *el = NULL; + + val.data = discard_const_p(uint8_t, str); + val.length = strlen(str); +@@ -524,7 +527,25 @@ int ldb_msg_add_string(struct ldb_message *msg, + return LDB_SUCCESS; + } + +- return ldb_msg_add_value(msg, attr_name, &val, NULL); ++ ret = ldb_msg_add_value(msg, attr_name, &val, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (flags != 0) { ++ el->flags = flags; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ add a string element to a message ++*/ ++int ldb_msg_add_string(struct ldb_message *msg, ++ const char *attr_name, const char *str) ++{ ++ return ldb_msg_add_string_flags(msg, attr_name, str, 0); + } + + /* +@@ -586,6 +607,142 @@ int ldb_msg_add_fmt(struct ldb_message *msg, + return ldb_msg_add_steal_value(msg, attr_name, &val); + } + ++static int ldb_msg_append_value_impl(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags, ++ struct ldb_message_element **return_el) ++{ ++ struct ldb_message_element *el = NULL; ++ int ret; ++ ++ ret = ldb_msg_add_empty(msg, attr_name, flags, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (return_el != NULL) { ++ *return_el = el; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ append a value to a message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags) ++{ ++ return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL); ++} ++ ++/* ++ append a value to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags) ++{ ++ int ret; ++ struct ldb_message_element *el = NULL; ++ ++ ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el); ++ if (ret == LDB_SUCCESS) { ++ talloc_steal(el->values, val->data); ++ } ++ return ret; ++} ++ ++/* ++ append a string element to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a string element to a message ++*/ ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = discard_const_p(uint8_t, str); ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a DN element to a message ++ WARNING: this uses the linearized string from the dn, and does not ++ copy the string. ++*/ ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags) ++{ ++ char *str = ldb_dn_alloc_linearized(msg, dn); ++ ++ if (str == NULL) { ++ /* we don't want to have unknown DNs added */ ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ return ldb_msg_append_steal_string(msg, attr_name, str, flags); ++} ++ ++/* ++ append a printf formatted element to a message ++*/ ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) ++{ ++ struct ldb_val val; ++ va_list ap; ++ char *str = NULL; ++ ++ va_start(ap, fmt); ++ str = talloc_vasprintf(msg, fmt, ap); ++ va_end(ap); ++ ++ if (str == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ + /* + compare two ldb_message_element structures + assumes case sensitive comparison +diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h +index 129beefeaf5..63d8aedd672 100644 +--- a/lib/ldb/include/ldb.h ++++ b/lib/ldb/include/ldb.h +@@ -2002,12 +2002,36 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + struct ldb_val *val); + int ldb_msg_add_steal_string(struct ldb_message *msg, + const char *attr_name, char *str); ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); + int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str); + int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn); + int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); ++/** ++ append a element to a ldb_message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags); ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags); ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); + + /** + compare two message elements - return 0 on match +-- +2.25.1 diff --git a/backport-0013-CVE-2022-2031-CVE-2022-32744.patch b/backport-0013-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..38a4959de5b1b36ac95ce3909c704c8c99ef395f --- /dev/null +++ b/backport-0013-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,475 @@ +From b8a81c06357f0360dbb3b59b1da1108bd1574810 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 1 Oct 2021 16:14:37 +1300 +Subject: [PATCH] CVE-2020-25718 kdc: Confirm the RODC was allowed to issue a + particular ticket + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Joseph Sutton +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/auth/sam.c | 5 +- + source4/dsdb/common/rodc_helper.c | 47 ++++---- + source4/kdc/mit_samba.c | 6 +- + source4/kdc/pac-glue.c | 106 +++++++++++++++++- + source4/kdc/pac-glue.h | 12 +- + source4/kdc/wdc-samba4.c | 40 ++++++- + source4/rpc_server/drsuapi/getncchanges.c | 11 +- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 1 + + 8 files changed, 187 insertions(+), 41 deletions(-) + +diff --git a/source4/auth/sam.c b/source4/auth/sam.c +index 39e48c2..93b41be 100644 +--- a/source4/auth/sam.c ++++ b/source4/auth/sam.c +@@ -57,7 +57,10 @@ + \ + "pwdLastSet", \ + "msDS-UserPasswordExpiryTimeComputed", \ +- "accountExpires" ++ "accountExpires", \ ++ \ ++ /* Needed for RODC rule processing */ \ ++ "msDS-KrbTgtLinkBL" + + const char *krbtgt_attrs[] = { + KRBTGT_ATTRS, NULL +diff --git a/source4/dsdb/common/rodc_helper.c b/source4/dsdb/common/rodc_helper.c +index 3a9636a..39f3b59 100644 +--- a/source4/dsdb/common/rodc_helper.c ++++ b/source4/dsdb/common/rodc_helper.c +@@ -47,19 +47,18 @@ bool sid_list_match(uint32_t num_sids1, + + /* + * Return an array of SIDs from a ldb_message given an attribute name assumes +- * the SIDs are in NDR form (with additional sids applied on the end). ++ * the SIDs are in NDR form (with primary_sid applied on the start). + */ +-WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, +- struct ldb_message *msg, +- TALLOC_CTX *mem_ctx, +- const char *attr, +- uint32_t *num_sids, +- struct dom_sid **sids, +- const struct dom_sid *additional_sids, +- unsigned int num_additional) ++static WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, ++ struct ldb_message *msg, ++ TALLOC_CTX *mem_ctx, ++ const char *attr, ++ uint32_t *num_sids, ++ struct dom_sid **sids, ++ const struct dom_sid *primary_sid) + { + struct ldb_message_element *el; +- unsigned int i, j; ++ unsigned int i; + + el = ldb_msg_find_element(msg, attr); + if (!el) { +@@ -69,24 +68,25 @@ WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx, + + /* Make array long enough for NULL and additional SID */ + (*sids) = talloc_array(mem_ctx, struct dom_sid, +- el->num_values + num_additional); ++ el->num_values + 1); + W_ERROR_HAVE_NO_MEMORY(*sids); + +- for (i=0; inum_values; i++) { ++ (*sids)[0] = *primary_sid; ++ ++ for (i = 0; inum_values; i++) { + enum ndr_err_code ndr_err; ++ struct dom_sid sid = { 0, }; + +- ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &(*sids)[i], ++ ndr_err = ndr_pull_struct_blob_all_noalloc(&el->values[i], &sid, + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return WERR_INTERNAL_DB_CORRUPTION; + } ++ /* Primary SID is already in position zero. */ ++ (*sids)[i+1] = sid; + } + +- for (j = 0; j < num_additional; j++) { +- (*sids)[i++] = additional_sids[j]; +- } +- +- *num_sids = i; ++ *num_sids = i+1; + + return WERR_OK; + } +@@ -131,6 +131,7 @@ WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx, + } + + WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ctx, ++ const struct dom_sid *rodc_machine_account_sid, + struct ldb_message *rodc_msg, + struct ldb_message *obj_msg, + uint32_t num_token_sids, +@@ -190,6 +191,12 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct + return WERR_DS_DRA_SECRETS_DENIED; + } + ++ /* The RODC can replicate and print tickets for itself. */ ++ if (dom_sid_equal(&token_sids[0], rodc_machine_account_sid)) { ++ TALLOC_FREE(frame); ++ return WERR_OK; ++ } ++ + if (never_reveal_sids && + sid_list_match(num_token_sids, + token_sids, +@@ -218,6 +225,7 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to_sid_list(struct ldb_context *sam_ct + * rather than relying on the caller providing those + */ + WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, ++ struct dom_sid *rodc_machine_account_sid, + struct ldb_message *rodc_msg, + struct ldb_message *obj_msg) + { +@@ -244,12 +252,13 @@ WERROR samdb_confirm_rodc_allowed_to_repl_to(struct ldb_context *sam_ctx, + frame, "tokenGroups", + &num_token_sids, + &token_sids, +- object_sid, 1); ++ object_sid); + if (!W_ERROR_IS_OK(werr) || token_sids==NULL) { + return WERR_DS_DRA_SECRETS_DENIED; + } + + werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(sam_ctx, ++ rodc_machine_account_sid, + rodc_msg, + obj_msg, + num_token_sids, +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 04be462..c6fa6af 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -440,7 +440,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + &logon_info_blob, + cred_ndr_ptr, + &upn_dns_info_blob, +- NULL, NULL); ++ NULL, NULL, ++ NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); + return EINVAL; +@@ -568,7 +569,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + &pac_blob, + NULL, + &upn_blob, +- NULL, NULL); ++ NULL, NULL, ++ NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; + goto done; +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index f0d61bb..92171fd 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -35,6 +35,7 @@ + #include "libcli/security/security.h" + #include "dsdb/samdb/samdb.h" + #include "auth/kerberos/pac_utils.h" ++#include "source4/dsdb/common/util.h" + + static + NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, +@@ -752,13 +753,19 @@ int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, + return 0; + } + ++/* ++ * We return not just the blobs, but also the user_info_dc because we ++ * will need, in the RODC case, to confirm that the returned user is ++ * permitted to be replicated to the KDC ++ */ + NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *p, + DATA_BLOB **_logon_info_blob, + DATA_BLOB **_cred_ndr_blob, + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, +- const krb5_boolean *pac_request) ++ const krb5_boolean *pac_request, ++ struct auth_user_info_dc **_user_info_dc) + { + struct auth_user_info_dc *user_info_dc; + DATA_BLOB *logon_blob = NULL; +@@ -856,7 +863,15 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + } + } + +- TALLOC_FREE(user_info_dc); ++ /* ++ * Return to the caller to allow a check on the allowed/denied ++ * RODC replication groups ++ */ ++ if (_user_info_dc == NULL) { ++ TALLOC_FREE(user_info_dc); ++ } else { ++ *_user_info_dc = user_info_dc; ++ } + *_logon_info_blob = logon_blob; + if (_cred_ndr_blob != NULL) { + *_cred_ndr_blob = cred_blob; +@@ -1123,3 +1138,90 @@ out: + TALLOC_FREE(frame); + return code; + } ++ ++ ++/* ++ * In the RODC case, to confirm that the returned user is permitted to ++ * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc ++ */ ++WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_object_sids, ++ struct dom_sid *object_sids, ++ struct samba_kdc_entry *rodc, ++ struct samba_kdc_entry *object) ++{ ++ int ret; ++ WERROR werr; ++ TALLOC_CTX *frame = talloc_stackframe(); ++ const char *rodc_attrs[] = { "msDS-KrbTgtLink", ++ "msDS-NeverRevealGroup", ++ "msDS-RevealOnDemandGroup", ++ "userAccountControl", ++ "objectSid", ++ NULL }; ++ struct ldb_result *rodc_machine_account = NULL; ++ struct ldb_dn *rodc_machine_account_dn = samdb_result_dn(rodc->kdc_db_ctx->samdb, ++ frame, ++ rodc->msg, ++ "msDS-KrbTgtLinkBL", ++ NULL); ++ const struct dom_sid *rodc_machine_account_sid = NULL; ++ ++ if (rodc_machine_account_dn == NULL) { ++ DBG_ERR("krbtgt account %s has no msDS-KrbTgtLinkBL to find RODC machine account for allow/deny list\n", ++ ldb_dn_get_linearized(rodc->msg->dn)); ++ TALLOC_FREE(frame); ++ return WERR_DS_DRA_BAD_DN; ++ } ++ ++ /* ++ * Follow the link and get the RODC account (the krbtgt ++ * account is the krbtgt_XXX account, but the ++ * msDS-NeverRevealGroup and msDS-RevealOnDemandGroup is on ++ * the RODC$ account) ++ * ++ * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID lists ++ * out of the extended DNs ++ */ ++ ++ ret = dsdb_search_dn(rodc->kdc_db_ctx->samdb, ++ frame, ++ &rodc_machine_account, ++ rodc_machine_account_dn, ++ rodc_attrs, ++ DSDB_SEARCH_SHOW_EXTENDED_DN); ++ if (ret != LDB_SUCCESS) { ++ DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: %s\n", ++ ldb_dn_get_linearized(rodc_machine_account_dn), ++ ldb_dn_get_linearized(rodc->msg->dn), ++ ldb_errstring(rodc->kdc_db_ctx->samdb)); ++ TALLOC_FREE(frame); ++ return WERR_DS_DRA_BAD_DN; ++ } ++ ++ if (rodc_machine_account->count != 1) { ++ DBG_ERR("Failed to fetch RODC machine account %s pointed to by %s to check allow/deny list: (%d)\n", ++ ldb_dn_get_linearized(rodc_machine_account_dn), ++ ldb_dn_get_linearized(rodc->msg->dn), ++ rodc_machine_account->count); ++ TALLOC_FREE(frame); ++ return WERR_DS_DRA_BAD_DN; ++ } ++ ++ /* if the object SID is equal to the user_sid, allow */ ++ rodc_machine_account_sid = samdb_result_dom_sid(frame, ++ rodc_machine_account->msgs[0], ++ "objectSid"); ++ if (rodc_machine_account_sid == NULL) { ++ return WERR_DS_DRA_BAD_DN; ++ } ++ ++ werr = samdb_confirm_rodc_allowed_to_repl_to_sid_list(rodc->kdc_db_ctx->samdb, ++ rodc_machine_account_sid, ++ rodc_machine_account->msgs[0], ++ object->msg, ++ num_object_sids, ++ object_sids); ++ ++ TALLOC_FREE(frame); ++ return werr; ++} +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 1b6264c..3b761f4 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -52,7 +52,8 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + DATA_BLOB **_cred_ndr_blob, + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, +- const krb5_boolean *pac_request); ++ const krb5_boolean *pac_request, ++ struct auth_user_info_dc **_user_info_dc); + NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *skdc_entry, + DATA_BLOB **_logon_info_blob); +@@ -82,3 +83,12 @@ krb5_error_code samba_kdc_validate_pac_blob( + krb5_context context, + struct samba_kdc_entry *client_skdc_entry, + const krb5_pac pac); ++ ++/* ++ * In the RODC case, to confirm that the returned user is permitted to ++ * be replicated to the KDC (krbgtgt_xxx user) represented by *rodc ++ */ ++WERROR samba_rodc_confirm_user_is_allowed(uint32_t num_sids, ++ struct dom_sid *sids, ++ struct samba_kdc_entry *rodc, ++ struct samba_kdc_entry *object); +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index b73dc84..51640b1 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -27,6 +27,7 @@ + #include "kdc/pac-glue.h" + #include "sdb.h" + #include "sdb_hdb.h" ++#include "librpc/gen_ndr/auth.h" + + /* + * Given the right private pointer from hdb_samba4, +@@ -68,7 +69,8 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + cred_ndr_ptr, + &upn_blob, + &pac_attrs_blob, +- pac_request); ++ pac_request, ++ NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return EINVAL; +@@ -161,9 +163,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + } + } + +- /* If the krbtgt was generated by an RODC, and we are not that ++ /* ++ * If the krbtgt was generated by an RODC, and we are not that + * RODC, then we need to regenerate the PAC - we can't trust +- * it */ ++ * it, and confirm that the RODC was permitted to print this ticket ++ * ++ * Becasue of the samba_kdc_validate_pac_blob() step we can be ++ * sure that the record in 'client' matches the SID in the ++ * original PAC. ++ */ + ret = samba_krbtgt_is_in_db(krbtgt_skdc_entry, &is_in_db, &is_untrusted); + if (ret != 0) { + talloc_free(mem_ctx); +@@ -237,6 +245,8 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + + if (is_untrusted) { + struct samba_kdc_entry *client_skdc_entry = NULL; ++ struct auth_user_info_dc *user_info_dc = NULL; ++ WERROR werr; + + if (client == NULL) { + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; +@@ -247,12 +257,30 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + + nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, + &pac_blob, NULL, &upn_blob, +- NULL, NULL); ++ NULL, NULL, ++ &user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); +- return EINVAL; ++ return KRB5KDC_ERR_TGT_REVOKED; ++ } ++ ++ /* ++ * Now check if the SID list in the user_info_dc ++ * intersects correctly with the RODC allow/deny ++ * lists ++ */ ++ ++ werr = samba_rodc_confirm_user_is_allowed(user_info_dc->num_sids, ++ user_info_dc->sids, ++ krbtgt_skdc_entry, ++ client_skdc_entry); ++ if (!W_ERROR_IS_OK(werr)) { ++ talloc_free(mem_ctx); ++ return KRB5KDC_ERR_TGT_REVOKED; + } +- } else { ++ } ++ ++ if (!is_untrusted) { + pac_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (!pac_blob) { + talloc_free(mem_ctx); +diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c +index 0d36a94..7084801 100644 +--- a/source4/rpc_server/drsuapi/getncchanges.c ++++ b/source4/rpc_server/drsuapi/getncchanges.c +@@ -1177,7 +1177,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, + NULL }; + const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL }; + struct ldb_result *rodc_res = NULL, *obj_res = NULL; +- const struct dom_sid *object_sid = NULL; + WERROR werr; + + DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n", +@@ -1261,15 +1260,6 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, + ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &obj_res, obj_dn, obj_attrs, 0); + if (ret != LDB_SUCCESS || obj_res->count != 1) goto failed; + +- /* if the object SID is equal to the user_sid, allow */ +- object_sid = samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"); +- if (object_sid == NULL) { +- goto failed; +- } +- if (dom_sid_equal(user_sid, object_sid)) { +- goto allowed; +- } +- + /* + * Must be an RODC account at this point, verify machine DN matches the + * SID account +@@ -1287,6 +1277,7 @@ static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state, + } + + werr = samdb_confirm_rodc_allowed_to_repl_to(b_state->sam_ctx_system, ++ user_sid, + rodc_res->msgs[0], + obj_res->msgs[0]); + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 11e8280..171b269 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -2810,6 +2810,7 @@ static bool sam_rodc_access_check(struct ldb_context *sam_ctx, + if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied; + + werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx, ++ user_sid, + rodc_res->msgs[0], + obj_res->msgs[0]); + +-- +2.27.0 + diff --git a/backport-0013-CVE-2022-32746.patch b/backport-0013-CVE-2022-32746.patch new file mode 100644 index 0000000000000000000000000000000000000000..139c66ae5d365999d06d409ed6d183be5207abfb --- /dev/null +++ b/backport-0013-CVE-2022-32746.patch @@ -0,0 +1,895 @@ +From f419753d1c7a373fb32ffe20930a6e084e44b44d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:27:37 +1300 +Subject: [PATCH 13/99] CVE-2022-32746 ldb: Make use of functions for appending + to an ldb_message + +This aims to minimise usage of the error-prone pattern of searching for +a just-added message element in order to make modifications to it (and +potentially finding the wrong element). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/ldb_map/ldb_map.c | 5 +- + lib/ldb/ldb_map/ldb_map_inbound.c | 9 +- + lib/ldb/modules/rdn_name.c | 22 +--- + source3/passdb/pdb_samba_dsdb.c | 14 +-- + source4/dns_server/dnsserver_common.c | 12 +- + source4/dsdb/common/util.c | 114 ++++++++++++++---- + source4/dsdb/samdb/ldb_modules/descriptor.c | 10 +- + source4/dsdb/samdb/ldb_modules/objectguid.c | 20 +-- + .../dsdb/samdb/ldb_modules/partition_init.c | 14 +-- + .../dsdb/samdb/ldb_modules/repl_meta_data.c | 24 +--- + source4/dsdb/samdb/ldb_modules/samldb.c | 78 +++++------- + .../samdb/ldb_modules/tombstone_reanimate.c | 12 +- + source4/nbt_server/wins/winsdb.c | 13 +- + source4/rpc_server/lsa/dcesrv_lsa.c | 55 +++------ + source4/winbind/idmap.c | 10 +- + 15 files changed, 183 insertions(+), 229 deletions(-) + +diff --git a/lib/ldb/ldb_map/ldb_map.c b/lib/ldb/ldb_map/ldb_map.c +index b453dff..c7b0c22 100644 +--- a/lib/ldb/ldb_map/ldb_map.c ++++ b/lib/ldb/ldb_map/ldb_map.c +@@ -946,10 +946,7 @@ struct ldb_request *map_build_fixup_req(struct map_context *ac, + if ( ! dn || ! ldb_dn_validate(msg->dn)) { + goto failed; + } +- if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { ++ if (ldb_msg_append_string(msg, IS_MAPPED, dn, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git a/lib/ldb/ldb_map/ldb_map_inbound.c b/lib/ldb/ldb_map/ldb_map_inbound.c +index 861c4c1..b8caa0f 100644 +--- a/lib/ldb/ldb_map/ldb_map_inbound.c ++++ b/lib/ldb/ldb_map/ldb_map_inbound.c +@@ -568,12 +568,9 @@ static int map_modify_do_local(struct map_context *ac) + /* No local record present, add it instead */ + /* Add local 'IS_MAPPED' */ + /* TODO: use GUIDs here instead */ +- if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED, +- LDB_FLAG_MOD_ADD, NULL) != 0) { +- return LDB_ERR_OPERATIONS_ERROR; +- } +- ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, +- ac->remote_req->op.mod.message->dn); ++ ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED, ++ ac->remote_req->op.mod.message->dn, ++ LDB_FLAG_MOD_ADD); + if (ret != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } +diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c +index 25cffe0..3cb62bf 100644 +--- a/lib/ldb/modules/rdn_name.c ++++ b/lib/ldb/modules/rdn_name.c +@@ -308,16 +308,10 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares) + } + rdn_val = ldb_val_dup(msg, rdn_val_p); + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } +- if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } + +@@ -466,11 +460,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +@@ -479,11 +469,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c +index 0753d38..b8328e8 100644 +--- a/source3/passdb/pdb_samba_dsdb.c ++++ b/source3/passdb/pdb_samba_dsdb.c +@@ -2858,18 +2858,10 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m, + } + + msg->num_elements = 0; +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_empty() failed\n")); +- TALLOC_FREE(tmp_ctx); +- ldb_transaction_cancel(state->ldb); +- return false; +- } +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &new_val, NULL); +- if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_value() failed\n")); ++ DEBUG(0, ("ldb_msg_append_value() failed\n")); + TALLOC_FREE(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return false; +diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c +index 420d141..814ffb3 100644 +--- a/source4/dns_server/dnsserver_common.c ++++ b/source4/dns_server/dnsserver_common.c +@@ -1083,15 +1083,9 @@ WERROR dns_common_replace(struct ldb_context *samdb, + } + + if (was_tombstoned || become_tombstoned) { +- ret = ldb_msg_add_empty(msg, "dNSTombstoned", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- werr = DNS_ERR(SERVER_FAILURE); +- goto exit; +- } +- +- ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", +- become_tombstoned ? "TRUE" : "FALSE"); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "dNSTombstoned", "%s", ++ become_tombstoned ? "TRUE" : "FALSE"); + if (ret != LDB_SUCCESS) { + werr = DNS_ERR(SERVER_FAILURE); + goto exit; +diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c +index 00d816e..6e2356e 100644 +--- a/source4/dsdb/common/util.c ++++ b/source4/dsdb/common/util.c +@@ -919,6 +919,16 @@ int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct l + return ldb_msg_add_string(msg, attr_name, s); + } + ++int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_add_string_flags(msg, attr_name, s, flags); ++} ++ + /* + * Add an unsigned int element to a message + * +@@ -937,6 +947,12 @@ int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct + return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v); + } + ++int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ + /* + add a (signed) int64_t element to a message + */ +@@ -968,6 +984,68 @@ int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc + return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v); + } + ++/* ++ append a int element to a message ++*/ ++int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ ++/* ++ append a (signed) int64_t element to a message ++*/ ++int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int64_t v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int64_t (uint64_t) element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, uint64_t v, int flags) ++{ ++ return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags); ++} ++ + /* + add a samr_Password element to a message + */ +@@ -2804,15 +2882,8 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + tdo_msg->num_elements = 0; + TALLOC_FREE(tdo_msg->elements); + +- ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- ldb_transaction_cancel(ldb); +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming", +- &new_val, NULL); ++ ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(ldb); + TALLOC_FREE(frame); +@@ -3172,6 +3243,7 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb, + /* + adds the given GUID to the given ldb_message. This value is added + for the given attr_name (may be either "objectGUID" or "parentGUID"). ++ This function is used in processing 'add' requests. + */ + int dsdb_msg_add_guid(struct ldb_message *msg, + struct GUID *guid, +@@ -5675,7 +5747,8 @@ int dsdb_user_obj_set_defaults(struct ldb_context *ldb, + } + + /** +- * Sets 'sAMAccountType on user object based on userAccountControl ++ * Sets 'sAMAccountType on user object based on userAccountControl. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5687,21 +5760,19 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + { + int ret; + uint32_t account_type; +- struct ldb_message_element *el; + + account_type = ds_uf2atype(user_account_control); + if (account_type == 0) { + ldb_set_errstring(ldb, "dsdb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (account_type_p) { + *account_type_p = account_type; +@@ -5711,7 +5782,8 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + } + + /** +- * Determine and set primaryGroupID based on userAccountControl value ++ * Determine and set primaryGroupID based on userAccountControl value. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5723,17 +5795,15 @@ int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_messa + { + int ret; + uint32_t rid; +- struct ldb_message_element *el; + + rid = ds_uf2prim_group_rid(user_account_control); + +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "primaryGroupID", rid); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "primaryGroupID", rid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (group_rid_p) { + *group_rid_p = rid; +diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c +index daa08c2..4b01961 100644 +--- a/source4/dsdb/samdb/ldb_modules/descriptor.c ++++ b/source4/dsdb/samdb/ldb_modules/descriptor.c +@@ -857,14 +857,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); + } + +- ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", +- LDB_FLAG_MOD_REPLACE, +- &sd_element); +- if (ret != LDB_SUCCESS) { +- return ldb_oom(ldb); +- } +- ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", +- sd, NULL); ++ ret = ldb_msg_append_value(msg, "nTSecurityDescriptor", ++ sd, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } +diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c +index bc3260c..0fe995a 100644 +--- a/source4/dsdb/samdb/ldb_modules/objectguid.c ++++ b/source4/dsdb/samdb/ldb_modules/objectguid.c +@@ -41,7 +41,6 @@ + */ + static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + { +- struct ldb_message_element *el; + char *s; + int ret; + +@@ -54,16 +53,13 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + return LDB_ERR_OPERATIONS_ERROR; + } + +- ret = ldb_msg_add_string(msg, attr, s); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = ldb_msg_append_string(msg, attr, s, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +@@ -73,23 +69,19 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr, uint64_t v) + { +- struct ldb_message_element *el; + int ret; + + if (ldb_msg_find_element(msg, attr) != NULL) { + return LDB_SUCCESS; + } + +- ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = samdb_msg_append_uint64(ldb, msg, msg, attr, v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c +index 19033b4..a090382 100644 +--- a/source4/dsdb/samdb/ldb_modules/partition_init.c ++++ b/source4/dsdb/samdb/ldb_modules/partition_init.c +@@ -754,10 +754,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + + mod_msg->dn = ldb_dn_new(mod_msg, ldb, DSDB_PARTITION_DN); +- ret = ldb_msg_add_empty(mod_msg, DSDB_PARTITION_ATTR, LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } + + casefold_dn = ldb_dn_get_casefold(dn); + +@@ -797,18 +793,16 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + partition_record = talloc_asprintf(mod_msg, "%s:%s", casefold_dn, filename); + +- ret = ldb_msg_add_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record); ++ ret = ldb_msg_append_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { + /* this new partition is a partial replica */ +- ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } +- ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn)); ++ ret = ldb_msg_append_fmt(mod_msg, LDB_FLAG_MOD_ADD, ++ "partialReplica", "%s", ldb_dn_get_linearized(dn)); + if (ret != LDB_SUCCESS) { + return ret; + } +diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index 407e2b0..95c0504 100644 +--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3891,22 +3891,12 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are + ldb_operr(ldb)); + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); +@@ -5084,16 +5074,10 @@ static int replmd_name_modify(struct replmd_replicated_request *ar, + goto failed; + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c +index 1cbbc50..159df19 100644 +--- a/source4/dsdb/samdb/ldb_modules/samldb.c ++++ b/source4/dsdb/samdb/ldb_modules/samldb.c +@@ -1117,14 +1117,11 @@ static int samldb_rodc_add(struct samldb_ctx *ac) + return LDB_ERR_OTHER; + + found: +- ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber", +- LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL); +- if (ret != LDB_SUCCESS) { +- return ldb_operr(ldb); +- } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "msDS-SecondaryKrbTgtNumber", krbtgt_number); ++ ldb_msg_remove_attr(ac->msg, "msDS-SecondaryKrbTgtNumber"); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "msDS-SecondaryKrbTgtNumber", krbtgt_number, ++ LDB_FLAG_INTERNAL_DISABLE_VALIDATION); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } +@@ -1806,7 +1803,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + void *skip_allocate_sids = ldb_get_opaque(ldb, + "skip_allocate_sids"); +- struct ldb_message_element *el, *el2; ++ struct ldb_message_element *el; + struct dom_sid *sid; + int ret; + +@@ -1939,23 +1936,17 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + /* "isCriticalSystemObject" might be set */ + if (user_account_control & + (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "TRUE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "TRUE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "FALSE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "FALSE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ +@@ -2033,14 +2024,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, ac->msg, ac->msg, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + break; + } +@@ -2958,26 +2948,23 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + + if (old_atype != new_atype) { +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", new_atype); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "sAMAccountType", new_atype, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ + if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { + /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */ + ldb_msg_remove_attr(ac->msg, "lockoutTime"); +- ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", +- (NTTIME)0); ++ ret = samdb_msg_append_uint64(ldb, ac->msg, ac->msg, "lockoutTime", ++ (NTTIME)0, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "lockoutTime"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* +@@ -2988,14 +2975,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + * creating the attribute. + */ + if (old_is_critical != new_is_critical || old_atype != new_atype) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- new_is_critical ? "TRUE": "FALSE"); ++ ret = ldb_msg_append_string(ac->msg, "isCriticalSystemObject", ++ new_is_critical ? "TRUE": "FALSE", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + if (!ldb_msg_find_element(ac->msg, "primaryGroupID") && +@@ -3008,14 +2993,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "primaryGroupID", new_pgrid); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "primaryGroupID", new_pgrid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Propagate eventual "userAccountControl" attribute changes */ +@@ -3218,13 +3201,12 @@ static int samldb_lockout_time(struct samldb_ctx *ac) + + /* lockoutTime == 0 resets badPwdCount */ + ldb_msg_remove_attr(ac->msg, "badPwdCount"); +- ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, +- "badPwdCount", 0); ++ ret = samdb_msg_append_int(ldb, ac->msg, ac->msg, ++ "badPwdCount", 0, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "badPwdCount"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +@@ -3322,13 +3304,11 @@ static int samldb_group_type_change(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType", +- account_type); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, "sAMAccountType", ++ account_type, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +diff --git a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 5f8911c..99c5955 100644 +--- a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -294,14 +294,13 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, + "reanimate: Unrecognized account type!"); + } +- ret = samdb_msg_add_uint(ldb, ac->mod_msg, ac->mod_msg, +- "sAMAccountType", account_type); ++ ret = samdb_msg_append_uint(ldb, ac->mod_msg, ac->mod_msg, ++ "sAMAccountType", account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, + "reanimate: Failed to add sAMAccountType to restored object."); + } +- el = ldb_msg_find_element(ac->mod_msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + /* Default values set by Windows */ + ret = samdb_find_or_add_attribute(ldb, ac->mod_msg, +@@ -324,12 +323,11 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ret; + } + +- ret = ldb_msg_add_string(ac->mod_msg, "objectCategory", value); ++ ret = ldb_msg_append_string(ac->mod_msg, "objectCategory", value, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->mod_msg, "objectCategory"); +- el->flags = LDB_FLAG_MOD_ADD; + } + + return LDB_SUCCESS; +diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c +index 41a9fd8..88ed1cc 100644 +--- a/source4/nbt_server/wins/winsdb.c ++++ b/source4/nbt_server/wins/winsdb.c +@@ -99,13 +99,11 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion) + msg->dn = dn; + + +- ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_string(msg, "objectClass", "winsMaxVersion", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion"); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "maxVersion", "%llu", (long long)newMaxVersion); + if (ret != LDB_SUCCESS) goto failed; + + ret = ldb_modify(wins_db, msg); +@@ -776,8 +774,7 @@ static struct ldb_message *winsdb_message(struct ldb_context *ldb, + ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]); + } + if (rec->registered_by) { +- ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL); +- ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by); ++ ret |= ldb_msg_append_string(msg, "registeredBy", rec->registered_by, 0); + } + if (ret != LDB_SUCCESS) goto failed; + return msg; +diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c +index 831ebf4..dc6a2e7 100644 +--- a/source4/rpc_server/lsa/dcesrv_lsa.c ++++ b/source4/rpc_server/lsa/dcesrv_lsa.c +@@ -1752,12 +1752,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx, + goto done; + } + +- ret = ldb_msg_add_empty(dest, attribute, flags, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value); ++ ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -1848,13 +1843,7 @@ static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx, + continue; + } + +- ret = ldb_msg_add_empty(msg, attribute, +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = ldb_msg_add_value(msg, attribute, &v, NULL); ++ ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -2140,28 +2129,30 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call, + } + + if (add_incoming || del_incoming) { +- ret = ldb_msg_add_empty(msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_incoming) { +- ret = ldb_msg_add_value(msg, "trustAuthIncoming", +- &trustAuthIncoming, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthIncoming", ++ &trustAuthIncoming, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthIncoming", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + } + } + if (add_outgoing || del_outgoing) { +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_outgoing) { +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &trustAuthOutgoing, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -4607,14 +4598,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat + goto done; + } + +- ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo", +- &ft_blob, NULL); ++ ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo", ++ &ft_blob, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + status = NT_STATUS_NO_MEMORY; + goto done; +diff --git a/source4/winbind/idmap.c b/source4/winbind/idmap.c +index c944132..9ba2f53 100644 +--- a/source4/winbind/idmap.c ++++ b/source4/winbind/idmap.c +@@ -672,14 +672,8 @@ static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, + vals[1].data = (uint8_t *)hwm_string; + vals[1].length = strlen(hwm_string); + } else { +- ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD, +- NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NONE_MAPPED; +- goto failed; +- } +- +- ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string); ++ ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) + { + status = NT_STATUS_NONE_MAPPED; +-- +2.27.0 + diff --git a/backport-0014-CVE-2022-2031-CVE-2022-32744.patch b/backport-0014-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ab762518ace12b7d2b846c8947baa20d0065887 --- /dev/null +++ b/backport-0014-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,496 @@ +From 45ff2b32361fb87a4f4bbc61f2620e2006666f34 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 26 Oct 2021 20:42:41 +1300 +Subject: [PATCH] CVE-2020-25719 s4:kdc: Add KDC support for PAC_REQUESTER_SID + PAC buffer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/mit_samba.c | 4 +- + source4/kdc/pac-glue.c | 163 +++++++++++++++++++++++++++++++++++---- + source4/kdc/pac-glue.h | 2 + + source4/kdc/wdc-samba4.c | 34 +++++++- + 4 files changed, 185 insertions(+), 18 deletions(-) + +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index a5c6010..dc331cb 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -448,7 +448,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + &logon_info_blob, + cred_ndr_ptr, + &upn_dns_info_blob, +- NULL, NULL, ++ NULL, NULL, NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); +@@ -474,6 +474,7 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + upn_dns_info_blob, + NULL, + NULL, ++ NULL, + pac); + + talloc_free(tmp_ctx); +@@ -553,6 +554,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + NULL, + &upn_blob, + NULL, NULL, ++ NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index 92171fd..34e2547 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -40,7 +40,8 @@ + static + NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, + const struct auth_user_info_dc *info, +- DATA_BLOB *pac_data) ++ DATA_BLOB *pac_data, ++ DATA_BLOB *requester_sid_blob) + { + struct netr_SamInfo3 *info3; + union PAC_INFO pac_info; +@@ -50,6 +51,9 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, + ZERO_STRUCT(pac_info); + + *pac_data = data_blob_null; ++ if (requester_sid_blob != NULL) { ++ *requester_sid_blob = data_blob_null; ++ } + + nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx, info, &info3); + if (!NT_STATUS_IS_OK(nt_status)) { +@@ -75,6 +79,25 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx, + return nt_status; + } + ++ if (requester_sid_blob != NULL && info->num_sids > 0) { ++ union PAC_INFO pac_requester_sid; ++ ++ ZERO_STRUCT(pac_requester_sid); ++ ++ pac_requester_sid.requester_sid.sid = info->sids[0]; ++ ++ ndr_err = ndr_push_union_blob(requester_sid_blob, mem_ctx, ++ &pac_requester_sid, ++ PAC_TYPE_REQUESTER_SID, ++ (ndr_push_flags_fn_t)ndr_push_PAC_INFO); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ nt_status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(1, ("PAC_REQUESTER_SID (presig) push failed: %s\n", ++ nt_errstr(nt_status))); ++ return nt_status; ++ } ++ } ++ + return NT_STATUS_OK; + } + +@@ -460,6 +483,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + const DATA_BLOB *cred_blob, + const DATA_BLOB *upn_blob, + const DATA_BLOB *pac_attrs_blob, ++ const DATA_BLOB *requester_sid_blob, + const DATA_BLOB *deleg_blob, + krb5_pac *pac) + { +@@ -467,6 +491,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + krb5_data cred_data; + krb5_data upn_data; + krb5_data pac_attrs_data; ++ krb5_data requester_sid_data; + krb5_data deleg_data; + krb5_error_code ret; + #ifdef SAMBA4_USES_HEIMDAL +@@ -524,6 +549,20 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + } + } + ++ ZERO_STRUCT(requester_sid_data); ++ if (requester_sid_blob != NULL) { ++ ret = smb_krb5_copy_data_contents(&requester_sid_data, ++ requester_sid_blob->data, ++ requester_sid_blob->length); ++ if (ret != 0) { ++ smb_krb5_free_data_contents(context, &logon_data); ++ smb_krb5_free_data_contents(context, &cred_data); ++ smb_krb5_free_data_contents(context, &upn_data); ++ smb_krb5_free_data_contents(context, &pac_attrs_data); ++ return ret; ++ } ++ } ++ + ZERO_STRUCT(deleg_data); + if (deleg_blob != NULL) { + ret = smb_krb5_copy_data_contents(&deleg_data, +@@ -534,6 +573,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + return ret; + } + } +@@ -544,6 +584,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -554,6 +595,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &cred_data); + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -566,6 +608,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + if (ret != 0) { + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -585,6 +628,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + if (ret != 0) { + smb_krb5_free_data_contents(context, &upn_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -597,6 +641,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + smb_krb5_free_data_contents(context, &upn_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + smb_krb5_free_data_contents(context, &deleg_data); + return ret; + } +@@ -607,6 +652,18 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + PAC_TYPE_ATTRIBUTES_INFO, + &pac_attrs_data); + smb_krb5_free_data_contents(context, &pac_attrs_data); ++ if (ret != 0) { ++ smb_krb5_free_data_contents(context, &requester_sid_data); ++ smb_krb5_free_data_contents(context, &deleg_data); ++ return ret; ++ } ++ } ++ ++ if (requester_sid_blob != NULL) { ++ ret = krb5_pac_add_buffer(context, *pac, ++ PAC_TYPE_REQUESTER_SID, ++ &requester_sid_data); ++ smb_krb5_free_data_contents(context, &requester_sid_data); + if (ret != 0) { + smb_krb5_free_data_contents(context, &deleg_data); + return ret; +@@ -765,6 +822,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, + const krb5_boolean *pac_request, ++ DATA_BLOB **_requester_sid_blob, + struct auth_user_info_dc **_user_info_dc) + { + struct auth_user_info_dc *user_info_dc; +@@ -772,6 +830,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + DATA_BLOB *cred_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *pac_attrs_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + NTSTATUS nt_status; + + *_logon_info_blob = NULL; +@@ -782,6 +841,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + if (_pac_attrs_blob != NULL) { + *_pac_attrs_blob = NULL; + } ++ if (_requester_sid_blob != NULL) { ++ *_requester_sid_blob = NULL; ++ } + + logon_blob = talloc_zero(mem_ctx, DATA_BLOB); + if (logon_blob == NULL) { +@@ -807,6 +869,13 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + } + } + ++ if (_requester_sid_blob != NULL) { ++ requester_sid_blob = talloc_zero(mem_ctx, DATA_BLOB); ++ if (requester_sid_blob == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } ++ + nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb, + lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx), + lpcfg_sam_name(p->kdc_db_ctx->lp_ctx), +@@ -824,7 +893,8 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + + nt_status = samba_get_logon_info_pac_blob(logon_blob, + user_info_dc, +- logon_blob); ++ logon_blob, ++ requester_sid_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("Building PAC LOGON INFO failed: %s\n", + nt_errstr(nt_status))); +@@ -880,6 +950,9 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + if (_pac_attrs_blob != NULL) { + *_pac_attrs_blob = pac_attrs_blob; + } ++ if (_requester_sid_blob != NULL) { ++ *_requester_sid_blob = requester_sid_blob; ++ } + return NT_STATUS_OK; + } + +@@ -933,7 +1006,7 @@ NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + } + + nt_status = samba_get_logon_info_pac_blob(mem_ctx, +- user_info_dc, pac_blob); ++ user_info_dc, pac_blob, NULL); + + return nt_status; + } +@@ -1083,6 +1156,52 @@ NTSTATUS samba_kdc_check_client_access(struct samba_kdc_entry *kdc_entry, + return nt_status; + } + ++static krb5_error_code samba_get_requester_sid(TALLOC_CTX *mem_ctx, ++ krb5_pac pac, ++ krb5_context context, ++ struct dom_sid *sid) ++{ ++ NTSTATUS nt_status; ++ enum ndr_err_code ndr_err; ++ krb5_error_code ret; ++ ++ DATA_BLOB pac_requester_sid_in; ++ krb5_data k5pac_requester_sid_in; ++ ++ union PAC_INFO info; ++ ++ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_REQUESTER_SID, ++ &k5pac_requester_sid_in); ++ if (ret != 0) { ++ talloc_free(tmp_ctx); ++ return ret; ++ } ++ ++ pac_requester_sid_in = data_blob_const(k5pac_requester_sid_in.data, ++ k5pac_requester_sid_in.length); ++ ++ ndr_err = ndr_pull_union_blob(&pac_requester_sid_in, tmp_ctx, &info, ++ PAC_TYPE_REQUESTER_SID, ++ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); ++ smb_krb5_free_data_contents(context, &k5pac_requester_sid_in); ++ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ++ nt_status = ndr_map_error2ntstatus(ndr_err); ++ DEBUG(0,("can't parse the PAC REQUESTER_SID: %s\n", nt_errstr(nt_status))); ++ talloc_free(tmp_ctx); ++ return EINVAL; ++ } ++ ++ *sid = info.requester_sid.sid; ++ ++ talloc_free(tmp_ctx); ++ return 0; ++} ++ + /* Does a parse and SID check, but no crypto. */ + krb5_error_code samba_kdc_validate_pac_blob( + krb5_context context, +@@ -1096,22 +1215,36 @@ krb5_error_code samba_kdc_validate_pac_blob( + krb5_error_code code; + bool ok; + +- code = kerberos_pac_to_user_info_dc(frame, +- pac, +- context, +- &pac_user_info, +- NULL, +- NULL); +- if (code != 0) { +- goto out; +- } ++ /* ++ * First, try to get the SID from the requester SID buffer in the PAC. ++ */ ++ code = samba_get_requester_sid(frame, pac, context, &pac_sid); ++ ++ if (code == ENOENT) { ++ /* ++ * If the requester SID buffer isn't present, fall back to the ++ * SID in the LOGON_INFO PAC buffer. ++ */ ++ code = kerberos_pac_to_user_info_dc(frame, ++ pac, ++ context, ++ &pac_user_info, ++ NULL, ++ NULL); ++ if (code != 0) { ++ goto out; ++ } ++ ++ if (pac_user_info->num_sids == 0) { ++ code = EINVAL; ++ goto out; ++ } + +- if (pac_user_info->num_sids == 0) { +- code = EINVAL; ++ pac_sid = pac_user_info->sids[0]; ++ } else if (code != 0) { + goto out; + } + +- pac_sid = pac_user_info->sids[0]; + client_sid = samdb_result_dom_sid(frame, + client_skdc_entry->msg, + "objectSid"); +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 3b761f4..9288924 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -32,6 +32,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context, + const DATA_BLOB *cred_blob, + const DATA_BLOB *upn_blob, + const DATA_BLOB *pac_attrs_blob, ++ const DATA_BLOB *requester_sid_blob, + const DATA_BLOB *deleg_blob, + krb5_pac *pac); + +@@ -53,6 +54,7 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + DATA_BLOB **_upn_info_blob, + DATA_BLOB **_pac_attrs_blob, + const krb5_boolean *pac_request, ++ DATA_BLOB **_requester_sid_blob, + struct auth_user_info_dc **_user_info_dc); + NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, + struct samba_kdc_entry *skdc_entry, +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index b6f7fd3..824a3f0 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -49,6 +49,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + DATA_BLOB *cred_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *pac_attrs_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + krb5_error_code ret; + NTSTATUS nt_status; + struct samba_kdc_entry *skdc_entry = +@@ -70,6 +71,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + &upn_blob, + &pac_attrs_blob, + pac_request, ++ &requester_sid_blob, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); +@@ -91,7 +93,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + + ret = samba_make_krb5_pac(context, logon_blob, cred_blob, + upn_blob, pac_attrs_blob, +- NULL, pac); ++ requester_sid_blob, NULL, pac); + + talloc_free(mem_ctx); + return ret; +@@ -123,6 +125,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + krb5_pac new_pac = NULL; + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + DATA_BLOB *deleg_blob = NULL; + krb5_error_code ret; + NTSTATUS nt_status; +@@ -139,6 +142,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + ssize_t kdc_checksum_idx = -1; + ssize_t tkt_checksum_idx = -1; + ssize_t attrs_info_idx = -1; ++ ssize_t requester_sid_idx = -1; + + if (!mem_ctx) { + return ENOMEM; +@@ -244,7 +248,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + + nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry, + &pac_blob, NULL, &upn_blob, +- NULL, NULL, ++ NULL, NULL, &requester_sid_blob, + &user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); +@@ -391,6 +395,18 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + } + attrs_info_idx = i; + break; ++ case PAC_TYPE_REQUESTER_SID: ++ if (requester_sid_idx != -1) { ++ DEBUG(1, ("requester sid type[%"PRIu32"] twice [%zd] and [%zu]: \n", ++ types[i], ++ requester_sid_idx, ++ i)); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return EINVAL; ++ } ++ requester_sid_idx = i; ++ break; + default: + continue; + } +@@ -513,6 +529,11 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + * we just add a place holder here. + */ + type_blob = data_blob_const(&zero_byte, 1); ++ ++ if (requester_sid_idx == -1 && requester_sid_blob != NULL) { ++ /* inject REQUESTER_SID behind */ ++ forced_next_type = PAC_TYPE_REQUESTER_SID; ++ } + break; + case PAC_TYPE_KDC_CHECKSUM: + /* +@@ -524,6 +545,15 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + case PAC_TYPE_ATTRIBUTES_INFO: + /* just copy... */ + break; ++ case PAC_TYPE_REQUESTER_SID: ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; + default: + /* just copy... */ + break; +-- +2.27.0 + diff --git a/backport-0015-CVE-2022-2031-CVE-2022-32744.patch b/backport-0015-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..1807cea1365152d3360f77f131ad5fc9a3358ac3 --- /dev/null +++ b/backport-0015-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,92 @@ +From 34eb92a2066cc403aac5a3708257b04a40ba19ee Mon Sep 17 00:00:00 2001 +Subject: [PATCH 19/99] s4:mit-kdb: Force canonicalization for looking up + principals + +See also +https://github.com/krb5/krb5/commit/ac8865a22138ab0c657208c41be8fd6bc7968148 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Isaac Boukris +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon Nov 29 09:32:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 90febd2a33b88af49af595fe0e995d6ba0f33a1b) + +[jsutton@samba.org Removed MIT knownfail changes] +--- + source4/heimdal/lib/hdb/hdb.h | 1 + + source4/kdc/db-glue.c | 7 ++++++- + source4/kdc/mit_samba.c | 8 ++++++++ + source4/kdc/sdb.h | 1 + + 4 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h +index 5ef9d9565f3..dafaffc6c2d 100644 +--- a/source4/heimdal/lib/hdb/hdb.h ++++ b/source4/heimdal/lib/hdb/hdb.h +@@ -63,6 +63,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; + #define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */ + #define HDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define HDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define HDB_F_FORCE_CANON 16384 /* force canonicalition */ + + /* hdb_capability_flags */ + #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 3a7e2176653..ac47fe78373 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -957,11 +957,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + krb5_clear_error_message(context); + goto out; + } +- } else if ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) { ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ + * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. + */ + ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); + if (ret) { +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index e015c5a52db..c2a604045d9 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -195,6 +195,14 @@ int mit_samba_get_principal(struct mit_samba_context *ctx, + return ENOMEM; + } + ++#if KRB5_KDB_API_VERSION >= 10 ++ /* ++ * The MIT KDC code that wants the canonical name in all lookups, and ++ * takes care to canonicalize only when appropriate. ++ */ ++ sflags |= SDB_F_FORCE_CANON; ++#endif ++ + if (kflags & KRB5_KDB_FLAG_CANONICALIZE) { + sflags |= SDB_F_CANON; + } +diff --git a/source4/kdc/sdb.h b/source4/kdc/sdb.h +index c929acccce6..a9115ec23d7 100644 +--- a/source4/kdc/sdb.h ++++ b/source4/kdc/sdb.h +@@ -116,6 +116,7 @@ struct sdb_entry_ex { + #define SDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */ + #define SDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define SDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define SDB_F_FORCE_CANON 16384 /* force canonicalition */ + + void sdb_free_entry(struct sdb_entry_ex *e); + void free_sdb_entry(struct sdb_entry *s); +-- +2.25.1 diff --git a/backport-0016-CVE-2022-2031-CVE-2022-32744.patch b/backport-0016-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..1165931eb4d0c1d042b92924f0f8771c9add8c4f --- /dev/null +++ b/backport-0016-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,28 @@ +From 06a0a75b16bace9c29568653d9e4bde4050c5ee5 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 21 Dec 2021 12:17:11 +0100 +Subject: [PATCH 20/99] s4:kdc: Also cannoicalize krbtgt principals when + enforcing canonicalization + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit f1ec950aeb47283a504018bafa21f54c3282e70c) +--- + source4/kdc/db-glue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index ac47fe78373..d017741e30a 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -920,7 +920,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; + +- if (flags & (SDB_F_CANON)) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { + /* + * When requested to do so, ensure that the + * both realm values in the principal are set +-- +2.25.1 diff --git a/backport-0017-CVE-2022-2031-CVE-2022-32744.patch b/backport-0017-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..73bc5c5e603a1fdcf8362f98abce4a54b584be6b --- /dev/null +++ b/backport-0017-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,27 @@ +From 33d5e5ad3a06ca6a1a62e64d323580ca60f068b8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 18 Nov 2021 16:22:34 +1300 +Subject: [PATCH 36/99] s4:torture: Fix typo + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9cfb88ba04818b5e9cec3c96422e8e4a3080d490) +--- + source4/torture/krb5/kdc-canon-heimdal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/torture/krb5/kdc-canon-heimdal.c b/source4/torture/krb5/kdc-canon-heimdal.c +index cd47182c0ef..059078a4ffb 100644 +--- a/source4/torture/krb5/kdc-canon-heimdal.c ++++ b/source4/torture/krb5/kdc-canon-heimdal.c +@@ -262,7 +262,7 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ + KRB5_NT_PRINCIPAL, + "krb5 libs unexpectedly " + "did not set principal " +- "as NT_SRV_HST!"); ++ "as NT_PRINCIPAL!"); + } else { + torture_assert_int_equal(test_context->tctx, + test_context->as_req.req_body.cname->name_type, +-- +2.25.1 diff --git a/backport-0018-CVE-2022-2031-CVE-2022-32744.patch b/backport-0018-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..9eabd0a4dd8594d2a6343d29b780400934dd5728 --- /dev/null +++ b/backport-0018-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,32 @@ +From 5556f97c782c9be9af47c76f2432bb8480bc0622 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:45 +1300 +Subject: [PATCH 38/99] kdc: Adjust SID mismatch error code to match Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit d5d22bf84a71492342287e54b555c9f024e7e71c) +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/pac-glue.c | 6 +----- + 3 files changed, 1 insertion(+), 48 deletions(-) + +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index e0e483662c0..2a96a683cd9 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -1237,11 +1237,7 @@ krb5_error_code samba_kdc_validate_pac_blob( + "PAC[%s] != CLI[%s]\n", + dom_sid_str_buf(&pac_sid, &buf1), + dom_sid_str_buf(client_sid, &buf2)); +-#if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */ +- code = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; +-#else /* Heimdal (where this is an enum) */ +- code = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; +-#endif ++ code = KRB5KDC_ERR_TGT_REVOKED; + goto out; + } + +-- +2.25.1 diff --git a/backport-0019-CVE-2022-2031-CVE-2022-32744.patch b/backport-0019-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..de5a05d828859a8245669ad3cc17026e4e17f23a --- /dev/null +++ b/backport-0019-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,30 @@ +From 93a5264dd68da57e172af50020f670631eeef263 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:15:41 +1300 +Subject: [PATCH 41/99] kdc: Always add the PAC if the header TGT is from an + RODC + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 690a00a40c0a3f77da6e4dca42b630f2793a98b8) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index ecd182702c3..8c3ce71529c 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -471,7 +471,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!server_skdc_entry->is_krbtgt) { ++ if (!is_untrusted && !server_skdc_entry->is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +-- +2.25.1 + diff --git a/backport-0020-CVE-2022-2031-CVE-2022-32744.patch b/backport-0020-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..7cb70f0e18ae8886ccd3092e799cdbddc1c5a355 --- /dev/null +++ b/backport-0020-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,73 @@ +From 72afa2641c24bd18a32463f0b0de7e91feb54290 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:42:22 +1300 +Subject: [PATCH 44/99] kdc: Don't include extra PAC buffers in service tickets + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 90025b6a4d250a15c0f988a9a9150ecfb63069ef) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 31 +++++++++++++++++-------- + 2 files changed, 21 insertions(+), 52 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 8c3ce71529c..17af76f4edb 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -132,6 +132,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + krb5_error_code ret; + NTSTATUS nt_status; + bool is_in_db, is_untrusted; ++ bool is_krbtgt; + size_t num_types = 0; + uint32_t *types = NULL; + uint32_t forced_next_type = 0; +@@ -471,7 +472,9 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!is_untrusted && !server_skdc_entry->is_krbtgt) { ++ is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); ++ ++ if (!is_untrusted && !is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +@@ -576,17 +579,25 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- /* just copy... */ +- break; ++ if (is_krbtgt) { ++ /* just copy... */ ++ break; ++ } else { ++ continue; ++ } + case PAC_TYPE_REQUESTER_SID: +- /* +- * Replace in the RODC case, otherwise +- * requester_sid_blob is NULL and we just copy. +- */ +- if (requester_sid_blob != NULL) { +- type_blob = *requester_sid_blob; ++ if (is_krbtgt) { ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; ++ } else { ++ continue; + } +- break; + default: + /* just copy... */ + break; +-- +2.25.1 diff --git a/backport-0021-CVE-2022-2031-CVE-2022-32744.patch b/backport-0021-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..6550e15be218bb52372173b53d3ea4251a40ee2b --- /dev/null +++ b/backport-0021-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,34 @@ +From 29f15fe2d92831dcf5f4eb6d295df866ff689ee3 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:53:49 +1300 +Subject: [PATCH 45/99] kdc: Remove PAC_TYPE_ATTRIBUTES_INFO from RODC-issued + tickets + +Windows ignores PAC_TYPE_ATTRIBUTES_INFO and always issues a PAC when +presented with an RODC-issued TGT. By removing this PAC buffer from +RODC-issued tickets, we ensure that an RODC-issued ticket will still +result in a PAC if it is first renewed or validated by the main DC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4b60e9516497c2e7f1545fe50887d0336b9893f2) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 14 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 17af76f4edb..713720bcb99 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -579,7 +579,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- if (is_krbtgt) { ++ if (!is_untrusted && is_krbtgt) { + /* just copy... */ + break; + } else { +-- +2.25.1 diff --git a/backport-0022-CVE-2022-2031-CVE-2022-32744.patch b/backport-0022-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..7b1481ff16c0e54379d3e77b26064c28591c4020 --- /dev/null +++ b/backport-0022-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,37 @@ +From 49aafce0a705d47ffd4753ce6c6f452c4f7aa882 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:54 +1300 +Subject: [PATCH 50/99] kdc: Require that PAC_REQUESTER_SID buffer is present + for TGTs + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Nov 30 03:33:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 38c5bad4a853b19fe9a51fb059e150b153c4632a) +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/wdc-samba4.c | 6 ++++++ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index b1d011c09a9..d7ce34fb3a9 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -459,6 +459,12 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + talloc_free(mem_ctx); + return EINVAL; + } ++ if (delegated_proxy_principal == NULL && requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return KRB5KDC_ERR_TGT_REVOKED; ++ } + + /* + * The server account may be set not to want the PAC. +-- +2.25.1 diff --git a/backport-0023-CVE-2022-2031-CVE-2022-32744.patch b/backport-0023-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2f079285b290bd5c59fa833d7745935c7861c75 --- /dev/null +++ b/backport-0023-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,55 @@ +From 3fc519edec0159535baa0b659861b73f40632110 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 7 Dec 2021 13:15:38 +1300 +Subject: [PATCH 51/99] kdc: Canonicalize realm for enterprise principals + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Dec 7 04:54:35 UTC 2021 on sn-devel-184 + +(cherry picked from commit 8bd7b316bd61ef35f6e0baa0b65f0ef00910112c) +Conflict: remove selftest/knownfail.d/kdc-enterprise selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/db-glue.c | 24 +++++------ + 4 files changed, 47 insertions(+), 79 deletions(-) + delete mode 100644 selftest/knownfail.d/kdc-enterprise + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index bed0ff773f9..5752ffb821c 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -980,19 +980,17 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + goto out; + } + +- if (smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) { +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ krb5_clear_error_message(context); ++ goto out; + } + } + +-- +2.25.1 diff --git a/backport-0024-CVE-2022-2031-CVE-2022-32744.patch b/backport-0024-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..dbfadfdc624c208ec8a33bfc774e0db5237a71be --- /dev/null +++ b/backport-0024-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,269 @@ +From c0395578c50fbc4f1946e2f5a065d94f67212eb0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 15 Jun 2022 19:37:39 +1200 +Subject: [PATCH 55/99] CVE-2022-2031 s4:kdc: Add MIT support for + ATTRIBUTES_INFO and REQUESTER_SID PAC buffers + +So that we do not confuse TGTs and kpasswd tickets, it is critical to +check that the REQUESTER_SID buffer exists in TGTs, and to ensure that +it is not propagated to service tickets. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton + +[jsutton@samba.org Brought in changes to add ATTRIBUTES_INFO and + REQUESTER_SID buffers to new PACs, and updated knownfails] + +[jsutton@samba.org Adjusted MIT knownfails] + +Conflict: remove selftest/knownfail_mit_kdc + +--- + source4/kdc/mit-kdb/kdb_samba_policies.c | 5 +- + source4/kdc/mit_samba.c | 93 +++++++++++++++++++++++- + source4/kdc/mit_samba.h | 1 + + 4 files changed, 94 insertions(+), 22 deletions(-) + +diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c +index 7bc9a7b3347..3b25fff410b 100644 +--- a/source4/kdc/mit-kdb/kdb_samba_policies.c ++++ b/source4/kdc/mit-kdb/kdb_samba_policies.c +@@ -159,6 +159,7 @@ done: + + static krb5_error_code ks_get_pac(krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -173,6 +174,7 @@ static krb5_error_code ks_get_pac(krb5_context context, + code = mit_samba_get_pac(mit_ctx, + context, + client, ++ server, + client_key, + pac); + if (code != 0) { +@@ -439,7 +441,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + */ + if (with_pac && generate_pac) { + DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name); +- code = ks_get_pac(context, client_entry, client_key, &pac); ++ code = ks_get_pac(context, client_entry, server, client_key, &pac); + if (code != 0) { + goto done; + } +@@ -490,6 +492,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + + code = ks_get_pac(context, + client_entry, ++ server, + client_key, + &pac); + if (code != 0 && code != ENOENT) { +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index c2a604045d9..df2ba0a906f 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -407,6 +407,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -417,9 +418,12 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + DATA_BLOB **cred_ndr_ptr = NULL; + DATA_BLOB cred_blob = data_blob_null; + DATA_BLOB *pcred_blob = NULL; ++ DATA_BLOB *pac_attrs_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + NTSTATUS nt_status; + krb5_error_code code; + struct samba_kdc_entry *skdc_entry; ++ bool is_krbtgt; + + skdc_entry = talloc_get_type_abort(client->e_data, + struct samba_kdc_entry); +@@ -438,12 +442,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + } + #endif + ++ is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ); ++ + nt_status = samba_kdc_get_pac_blobs(tmp_ctx, + skdc_entry, + &logon_info_blob, + cred_ndr_ptr, + &upn_dns_info_blob, +- NULL, NULL, NULL, ++ is_krbtgt ? &pac_attrs_blob : NULL, ++ NULL, ++ is_krbtgt ? &requester_sid_blob : NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); +@@ -471,8 +479,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + logon_info_blob, + pcred_blob, + upn_dns_info_blob, +- NULL, +- NULL, ++ pac_attrs_blob, ++ requester_sid_blob, + NULL, + pac); + +@@ -496,6 +504,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *deleg_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + struct samba_kdc_entry *client_skdc_entry = NULL; + struct samba_kdc_entry *krbtgt_skdc_entry = NULL; + struct samba_kdc_entry *server_skdc_entry = NULL; +@@ -511,8 +520,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + ssize_t upn_dns_info_idx = -1; + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; ++ ssize_t tkt_checksum_idx = -1; ++ ssize_t attrs_info_idx = -1; ++ ssize_t requester_sid_idx = -1; + krb5_pac new_pac = NULL; + bool ok; ++ bool is_krbtgt; + + /* Create a memory context early so code can use talloc_stackframe() */ + tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); +@@ -520,6 +533,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + return ENOMEM; + } + ++ is_krbtgt = ks_is_tgs_principal(ctx, server->princ); ++ + if (client != NULL) { + client_skdc_entry = + talloc_get_type_abort(client->e_data, +@@ -578,7 +593,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + NULL, + &upn_blob, + NULL, NULL, +- NULL, ++ &requester_sid_blob, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; +@@ -737,6 +752,45 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + kdc_checksum_idx = i; + break; ++ case PAC_TYPE_TICKET_CHECKSUM: ++ if (tkt_checksum_idx != -1) { ++ DBG_WARNING("ticket checksum type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ tkt_checksum_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ tkt_checksum_idx = i; ++ break; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (attrs_info_idx != -1) { ++ DBG_WARNING("attributes info type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ attrs_info_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ attrs_info_idx = i; ++ break; ++ case PAC_TYPE_REQUESTER_SID: ++ if (requester_sid_idx != -1) { ++ DBG_WARNING("requester sid type[%u] twice" ++ "[%zd] and [%zu]: \n", ++ types[i], ++ requester_sid_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ requester_sid_idx = i; ++ break; + default: + continue; + } +@@ -766,6 +820,13 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + code = EINVAL; + goto done; + } ++ if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) && ++ requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ code = KRB5KDC_ERR_TGT_REVOKED; ++ goto done; ++ } + + /* Build an updated PAC */ + code = krb5_pac_init(context, &new_pac); +@@ -831,6 +892,10 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + break; + case PAC_TYPE_SRV_CHECKSUM: ++ if (requester_sid_idx == -1 && requester_sid_blob != NULL) { ++ /* inject REQUESTER_SID */ ++ forced_next_type = PAC_TYPE_REQUESTER_SID; ++ } + /* + * This is generated in the main KDC code + */ +@@ -840,6 +905,26 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + * This is generated in the main KDC code + */ + continue; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (!is_untrusted && is_krbtgt) { ++ /* just copy... */ ++ break; ++ } ++ ++ continue; ++ case PAC_TYPE_REQUESTER_SID: ++ if (!is_krbtgt) { ++ continue; ++ } ++ ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; + default: + /* just copy... */ + break; +diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h +index 636c77ec97c..4431e82a1b2 100644 +--- a/source4/kdc/mit_samba.h ++++ b/source4/kdc/mit_samba.h +@@ -50,6 +50,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac); + +-- +2.25.1 diff --git a/backport-0025-CVE-2022-2031-CVE-2022-32744.patch b/backport-0025-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..7129cd48e45daaff36deeef141be076d726f3e80 --- /dev/null +++ b/backport-0025-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,34 @@ +From 6843c44a45044808f90687f85183e7111a465d1f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 16 Jun 2022 10:33:29 +1200 +Subject: [PATCH 56/99] heimdal:kdc: Accommodate NULL data parameter in + krb5_pac_get_buffer() + +Signed-off-by: Joseph Sutton +--- + source4/heimdal/lib/krb5/pac.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c +index 05bcc523080..100de904662 100644 +--- a/source4/heimdal/lib/krb5/pac.c ++++ b/source4/heimdal/lib/krb5/pac.c +@@ -394,10 +394,12 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, + if (p->pac->buffers[i].type != type) + continue; + +- ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); +- if (ret) { +- krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); +- return ret; ++ if (data) { ++ ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); ++ if (ret) { ++ krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); ++ return ret; ++ } + } + return 0; + } +-- +2.25.1 diff --git a/backport-0026-CVE-2022-2031-CVE-2022-32744.patch b/backport-0026-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..3089f6d279afd2934c8acebe2ce267a47f2657eb --- /dev/null +++ b/backport-0026-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,53 @@ +From 1b38a28bcaebdae0128518605a422a194747a60f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:17:02 +1200 +Subject: [PATCH 57/99] CVE-2022-2031 s4:kpasswd: Account for missing target + principal + +This field is supposed to be optional. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index 2117c1c1696..b53c1a4618a 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -143,16 +143,18 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + +- target_realm = smb_krb5_principal_get_realm( +- mem_ctx, context, target_principal); +- code = krb5_unparse_name_flags(context, +- target_principal, +- KRB5_PRINCIPAL_UNPARSE_NO_REALM, +- &target_name); +- if (code != 0) { +- DBG_WARNING("Failed to parse principal\n"); +- *error_string = "String conversion failed"; +- return KRB5_KPASSWD_HARDERROR; ++ if (target_principal != NULL) { ++ target_realm = smb_krb5_principal_get_realm( ++ mem_ctx, context, target_principal); ++ code = krb5_unparse_name_flags(context, ++ target_principal, ++ KRB5_PRINCIPAL_UNPARSE_NO_REALM, ++ &target_name); ++ if (code != 0) { ++ DBG_WARNING("Failed to parse principal\n"); ++ *error_string = "String conversion failed"; ++ return KRB5_KPASSWD_HARDERROR; ++ } + } + + if ((target_name != NULL && target_realm == NULL) || +-- +2.25.1 diff --git a/backport-0027-CVE-2022-2031-CVE-2022-32744.patch b/backport-0027-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e7ed931b1173aabcd625c5bd879e9390fddd815 --- /dev/null +++ b/backport-0027-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,165 @@ +From f6c5a60336de8fd67a2ef371dd2ee4cf75c53904 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:17:41 +1200 +Subject: [PATCH 58/99] CVE-2022-2031 s4:kpasswd: Add MIT fallback for decoding + setpw structure + +The target principal and realm fields of the setpw structure are +supposed to be optional, but in MIT Kerberos they are mandatory. For +better compatibility and ease of testing, fall back to parsing the +simpler (containing only the new password) structure if the MIT function +fails to decode it. + +Although the target principal and realm fields should be optional, one +is not supposed to specified without the other, so we don't have to deal +with the case where only one is specified. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 94 ++++++++++++++++++++++++++----- + 1 file changed, 79 insertions(+), 15 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index b53c1a4618a..9c4d2801669 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -28,6 +28,7 @@ + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "../lib/util/asn1.h" + + #define RFC3244_VERSION 0xff80 + +@@ -35,6 +36,52 @@ krb5_error_code decode_krb5_setpw_req(const krb5_data *code, + krb5_data **password_out, + krb5_principal *target_out); + ++/* ++ * A fallback for when MIT refuses to parse a setpw structure without the ++ * (optional) target principal and realm ++ */ ++static bool decode_krb5_setpw_req_simple(TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *decoded_data, ++ DATA_BLOB *clear_data) ++{ ++ struct asn1_data *asn1 = NULL; ++ bool ret; ++ ++ asn1 = asn1_init(mem_ctx, 3); ++ if (asn1 == NULL) { ++ return false; ++ } ++ ++ ret = asn1_load(asn1, *decoded_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_start_tag(asn1, ASN1_SEQUENCE(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_start_tag(asn1, ASN1_CONTEXT(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_read_OctetString(asn1, mem_ctx, clear_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_end_tag(asn1); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_end_tag(asn1); ++ ++out: ++ asn1_free(asn1); ++ ++ return ret; ++} ++ + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, +@@ -93,9 +140,10 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + const char **error_string) + { + krb5_context context = kdc->smb_krb5_context->krb5_context; ++ DATA_BLOB clear_data; + krb5_data k_dec_data; +- krb5_data *k_clear_data; +- krb5_principal target_principal; ++ krb5_data *k_clear_data = NULL; ++ krb5_principal target_principal = NULL; + krb5_error_code code; + DATA_BLOB password; + char *target_realm = NULL; +@@ -114,29 +162,45 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + code = decode_krb5_setpw_req(&k_dec_data, + &k_clear_data, + &target_principal); +- if (code != 0) { +- DBG_WARNING("decode_krb5_setpw_req failed: %s\n", +- error_message(code)); +- ok = kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to decode packet", +- kpasswd_reply); ++ if (code == 0) { ++ clear_data.data = (uint8_t *)k_clear_data->data; ++ clear_data.length = k_clear_data->length; ++ } else { ++ target_principal = NULL; ++ ++ /* ++ * The MIT decode failed, so fall back to trying the simple ++ * case, without target_principal. ++ */ ++ ok = decode_krb5_setpw_req_simple(mem_ctx, ++ decoded_data, ++ &clear_data); + if (!ok) { +- *error_string = "Failed to create reply"; +- return KRB5_KPASSWD_HARDERROR; ++ DBG_WARNING("decode_krb5_setpw_req failed: %s\n", ++ error_message(code)); ++ ok = kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to decode packet", ++ kpasswd_reply); ++ if (!ok) { ++ *error_string = "Failed to create reply"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ return 0; + } +- return 0; + } + + ok = convert_string_talloc_handle(mem_ctx, + lpcfg_iconv_handle(kdc->task->lp_ctx), + CH_UTF8, + CH_UTF16, +- (const char *)k_clear_data->data, +- k_clear_data->length, ++ clear_data.data, ++ clear_data.length, + (void **)&password.data, + &password.length); +- krb5_free_data(context, k_clear_data); ++ if (k_clear_data != NULL) { ++ krb5_free_data(context, k_clear_data); ++ } + if (!ok) { + DBG_WARNING("String conversion failed\n"); + *error_string = "String conversion failed"; +-- +2.25.1 diff --git a/backport-0028-CVE-2022-2031-CVE-2022-32744.patch b/backport-0028-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..41e48acbbca8d05eff883fae3f1694edab64df65 --- /dev/null +++ b/backport-0028-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,57 @@ +From 29ec8b2369b5f5e2a660a3165d2528982514a0f2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:21:06 +1200 +Subject: [PATCH 72/99] CVE-2022-2031 s4:kpasswd: Correctly generate error + strings + +The error_data we create already has an explicit length, and should not +be zero-terminated, so we omit the trailing null byte. Previously, +Heimdal builds would leave a superfluous trailing null byte on error +strings, while MIT builds would omit the final character. + +The two bytes added to the string's length are for the prepended error +code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/kpasswd-helper.c | 13 ++++++------- + 3 files changed, 6 insertions(+), 34 deletions(-) + +diff --git a/source4/kdc/kpasswd-helper.c b/source4/kdc/kpasswd-helper.c +index 995f54825b5..55a2f5b3bf6 100644 +--- a/source4/kdc/kpasswd-helper.c ++++ b/source4/kdc/kpasswd-helper.c +@@ -48,17 +48,16 @@ bool kpasswd_make_error_reply(TALLOC_CTX *mem_ctx, + } + + /* +- * The string 's' has two terminating nul-bytes which are also +- * reflected by 'slen'. Normally Kerberos doesn't expect that strings +- * are nul-terminated, but Heimdal does! ++ * The string 's' has one terminating nul-byte which is also ++ * reflected by 'slen'. We subtract it from the length. + */ +-#ifndef SAMBA4_USES_HEIMDAL +- if (slen < 2) { ++ if (slen < 1) { + talloc_free(s); + return false; + } +- slen -= 2; +-#endif ++ slen--; ++ ++ /* Two bytes are added to the length to account for the error code. */ + if (2 + slen < slen) { + talloc_free(s); + return false; +-- +2.25.1 diff --git a/backport-0029-CVE-2022-2031-CVE-2022-32744.patch b/backport-0029-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..e0d87a5967b3907c327f335c0c8f393b297e13e3 --- /dev/null +++ b/backport-0029-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,41 @@ +From 3a8da51396f3bf9d4caf8dbd4e75a0314aa47046 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:48:59 +1200 +Subject: [PATCH 73/99] CVE-2022-2031 s4:kpasswd: Don't return AP-REP on + failure + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +Conflict: remove selftest/knownfail_mit_kdc +--- + source4/kdc/kpasswd-service.c | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index 8f1679e4a28..a3c57a67dd1 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -253,6 +253,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &error_string); + if (code != 0) { ++ ap_rep_blob = data_blob_null; + error_code = code; + goto reply; + } +@@ -262,6 +263,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &enc_data_blob); + if (!NT_STATUS_IS_OK(status)) { ++ ap_rep_blob = data_blob_null; + error_code = KRB5_KPASSWD_HARDERROR; + error_string = talloc_asprintf(tmp_ctx, + "gensec_wrap failed - %s\n", +-- +2.25.1 diff --git a/backport-0030-CVE-2022-2031-CVE-2022-32744.patch b/backport-0030-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..c4a581f92d3abeb98f7e43e678ea66f409501a7b --- /dev/null +++ b/backport-0030-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,36 @@ +From cf9e37604409ba0c3c5904af40beb2975c309ad4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:29:34 +1200 +Subject: [PATCH 74/99] CVE-2022-2031 lib:krb5_wrap: Generate valid error codes + in smb_krb5_mk_error() + +The error code passed in will be an offset from ERROR_TABLE_BASE_krb5, +so we need to subtract that before creating the error. Heimdal does this +internally, so it isn't needed there. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +Conflict: remove selftest/knownfail_mit_kdc +--- + lib/krb5_wrap/krb5_samba.c | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c +index 76c2dcd2126..610efcc9b87 100644 +--- a/lib/krb5_wrap/krb5_samba.c ++++ b/lib/krb5_wrap/krb5_samba.c +@@ -237,7 +237,7 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, + return code; + } + +- errpkt.error = error_code; ++ errpkt.error = error_code - ERROR_TABLE_BASE_krb5; + + errpkt.text.length = 0; + if (e_text != NULL) { +-- +2.25.1 diff --git a/backport-0031-CVE-2022-2031-CVE-2022-32744.patch b/backport-0031-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8674279f63a8fb4356f3b544eb7b74a455aa250 --- /dev/null +++ b/backport-0031-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,38 @@ +From cf749fac346ef59c91a9ea87f5e7ddec2e5649c7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:49:43 +1200 +Subject: [PATCH 75/99] CVE-2022-2031 s4:kpasswd: Return a kpasswd error code + in KRB-ERROR + +If we attempt to return an error code outside of Heimdal's allowed range +[KRB5KDC_ERR_NONE, KRB5_ERR_RCSID), it will be replaced with a GENERIC +error, and the error text will be set to the meaningless result of +krb5_get_error_message(). Avoid this by ensuring the error code is in +the correct range. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/kpasswd-service.c | 2 +- + 3 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index a3c57a67dd1..b4706de1ad7 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -312,7 +312,7 @@ reply: + } + + code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context, +- error_code, ++ KRB5KDC_ERR_NONE + error_code, + NULL, /* e_text */ + &k_dec_data, + NULL, /* client */ +-- +2.25.1 diff --git a/backport-0032-CVE-2022-2031-CVE-2022-32744.patch b/backport-0032-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..57c2b35e20a32a78c58ba4341ef4f392935424aa --- /dev/null +++ b/backport-0032-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,245 @@ +From 198256e2184897300e1cea4343437c3b7b6f74ad Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:06:31 +1200 +Subject: [PATCH 76/99] CVE-2022-2031 gensec_krb5: Add helper function to check + if client sent an initial ticket + +This will be used in the kpasswd service to ensure that the client has +an initial ticket to kadmin/changepw, and not a service ticket. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/gensec/gensec_krb5.c | 20 +----- + source4/auth/gensec/gensec_krb5_helpers.c | 72 ++++++++++++++++++++++ + source4/auth/gensec/gensec_krb5_helpers.h | 32 ++++++++++ + source4/auth/gensec/gensec_krb5_internal.h | 47 ++++++++++++++ + source4/auth/gensec/wscript_build | 4 ++ + 5 files changed, 157 insertions(+), 18 deletions(-) + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.c + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.h + create mode 100644 source4/auth/gensec/gensec_krb5_internal.h + +diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c +index 7d87b3ac6b9..104e4639c44 100644 +--- a/source4/auth/gensec/gensec_krb5.c ++++ b/source4/auth/gensec/gensec_krb5.c +@@ -44,27 +44,11 @@ + #include "../lib/util/asn1.h" + #include "auth/kerberos/pac_utils.h" + #include "gensec_krb5.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" + + _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *); + +-enum GENSEC_KRB5_STATE { +- GENSEC_KRB5_SERVER_START, +- GENSEC_KRB5_CLIENT_START, +- GENSEC_KRB5_CLIENT_MUTUAL_AUTH, +- GENSEC_KRB5_DONE +-}; +- +-struct gensec_krb5_state { +- enum GENSEC_KRB5_STATE state_position; +- struct smb_krb5_context *smb_krb5_context; +- krb5_auth_context auth_context; +- krb5_data enc_ticket; +- krb5_keyblock *keyblock; +- krb5_ticket *ticket; +- bool gssapi; +- krb5_flags ap_req_options; +-}; +- + static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state) + { + if (!gensec_krb5_state->smb_krb5_context) { +diff --git a/source4/auth/gensec/gensec_krb5_helpers.c b/source4/auth/gensec/gensec_krb5_helpers.c +new file mode 100644 +index 00000000000..21f2f1e884e +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_helpers.c +@@ -0,0 +1,72 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "includes.h" ++#include "auth/auth.h" ++#include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++static struct gensec_krb5_state *get_private_state(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ if (strcmp(gensec_security->ops->name, "krb5") != 0) { ++ /* We require that the krb5 mechanism is being used. */ ++ return NULL; ++ } ++ ++ gensec_krb5_state = talloc_get_type(gensec_security->private_data, ++ struct gensec_krb5_state); ++ return gensec_krb5_state; ++} ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ gensec_krb5_state = get_private_state(gensec_security); ++ if (gensec_krb5_state == NULL) { ++ return -1; ++ } ++ ++ if (gensec_krb5_state->ticket == NULL) { ++ /* We don't have a ticket */ ++ return -1; ++ } ++ ++#ifdef SAMBA4_USES_HEIMDAL ++ return gensec_krb5_state->ticket->ticket.flags.initial; ++#else /* MIT KERBEROS */ ++ return (gensec_krb5_state->ticket->enc_part2->flags & TKT_FLG_INITIAL) ? 1 : 0; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} +diff --git a/source4/auth/gensec/gensec_krb5_helpers.h b/source4/auth/gensec/gensec_krb5_helpers.h +new file mode 100644 +index 00000000000..d7b694dad0c +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_helpers.h +@@ -0,0 +1,32 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++struct gensec_security; ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security); +diff --git a/source4/auth/gensec/gensec_krb5_internal.h b/source4/auth/gensec/gensec_krb5_internal.h +new file mode 100644 +index 00000000000..0bb796f1b2a +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_internal.h +@@ -0,0 +1,47 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "includes.h" ++#include "auth/gensec/gensec.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++enum GENSEC_KRB5_STATE { ++ GENSEC_KRB5_SERVER_START, ++ GENSEC_KRB5_CLIENT_START, ++ GENSEC_KRB5_CLIENT_MUTUAL_AUTH, ++ GENSEC_KRB5_DONE ++}; ++ ++struct gensec_krb5_state { ++ enum GENSEC_KRB5_STATE state_position; ++ struct smb_krb5_context *smb_krb5_context; ++ krb5_auth_context auth_context; ++ krb5_data enc_ticket; ++ krb5_keyblock *keyblock; ++ krb5_ticket *ticket; ++ bool gssapi; ++ krb5_flags ap_req_options; ++}; +diff --git a/source4/auth/gensec/wscript_build b/source4/auth/gensec/wscript_build +index d14a50ff273..20271f1665b 100644 +--- a/source4/auth/gensec/wscript_build ++++ b/source4/auth/gensec/wscript_build +@@ -18,6 +18,10 @@ bld.SAMBA_MODULE('gensec_krb5', + enabled=bld.AD_DC_BUILD_IS_ENABLED() + ) + ++bld.SAMBA_SUBSYSTEM('gensec_krb5_helpers', ++ source='gensec_krb5_helpers.c', ++ deps='gensec_krb5', ++ enabled=bld.AD_DC_BUILD_IS_ENABLED()) + + bld.SAMBA_MODULE('gensec_gssapi', + source='gensec_gssapi.c', +-- +2.25.1 diff --git a/backport-0033-CVE-2022-2031-CVE-2022-32744.patch b/backport-0033-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..03f901c20eb9f893f3f716849ccb4099932be402 --- /dev/null +++ b/backport-0033-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,80 @@ +From 69e742e6208bd471eb509795bd753a0c98392bf6 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 17:11:49 +1200 +Subject: [PATCH 78/99] s4:kpasswd: Restructure code for clarity + +View with 'git show -b'. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-heimdal.c | 46 +++++++++++++-------------- + 1 file changed, 22 insertions(+), 24 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-heimdal.c b/source4/kdc/kpasswd-service-heimdal.c +index 1a6c2b60d03..a0352d1ad35 100644 +--- a/source4/kdc/kpasswd-service-heimdal.c ++++ b/source4/kdc/kpasswd-service-heimdal.c +@@ -160,30 +160,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return 0; + } + +- if (chpw.targname != NULL && chpw.targrealm != NULL) { +- code = krb5_build_principal_ext(context, +- &target_principal, +- strlen(*chpw.targrealm), +- *chpw.targrealm, +- 0); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- code = copy_PrincipalName(chpw.targname, +- &target_principal->name); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- krb5_free_principal(context, target_principal); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- } else { ++ if (chpw.targname == NULL || chpw.targrealm == NULL) { + free_ChangePasswdDataMS(&chpw); + return kpasswd_change_password(kdc, + mem_ctx, +@@ -193,7 +170,28 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + kpasswd_reply, + error_string); + } ++ code = krb5_build_principal_ext(context, ++ &target_principal, ++ strlen(*chpw.targrealm), ++ *chpw.targrealm, ++ 0); ++ if (code != 0) { ++ free_ChangePasswdDataMS(&chpw); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } ++ code = copy_PrincipalName(chpw.targname, ++ &target_principal->name); + free_ChangePasswdDataMS(&chpw); ++ if (code != 0) { ++ krb5_free_principal(context, target_principal); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } + + if (target_principal->name.name_string.len >= 2) { + is_service_principal = true; +-- +2.25.1 diff --git a/backport-0034-CVE-2022-2031-CVE-2022-32744.patch b/backport-0034-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..e1e6a5275afbacaeb44bafc949a1702e55fbcb7f --- /dev/null +++ b/backport-0034-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,41 @@ +From b5adf7cc6d740c8f4f7b5888f106de24a1181da7 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 10:17:00 +0200 +Subject: [PATCH 79/99] CVE-2022-2031 testprogs: Fix auth with smbclient and + krb5 ccache + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton + +[jsutton@samba.org Fixed conflict and renamed --use-krb5-ccache to + --krb5-ccache] +--- + testprogs/blackbox/test_kpasswd_heimdal.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/testprogs/blackbox/test_kpasswd_heimdal.sh b/testprogs/blackbox/test_kpasswd_heimdal.sh +index 7351ce022d1..1e895daa162 100755 +--- a/testprogs/blackbox/test_kpasswd_heimdal.sh ++++ b/testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -72,7 +72,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + testit "change user password with 'samba-tool user password' (unforced)" \ + $VALGRIND $PYTHON $samba_tool user password -W$DOMAIN -U$TEST_USERNAME%$TEST_PASSWORD -k no --newpassword=$TEST_PASSWORD_NEW || failed=`expr $failed + 1` +@@ -85,7 +85,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + ########################################################### + ### check that a short password is rejected +-- +2.25.1 diff --git a/backport-0035-CVE-2022-2031-CVE-2022-32744.patch b/backport-0035-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..2150406be50f81ed04dfc6dd0577084f8f60c327 --- /dev/null +++ b/backport-0035-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,85 @@ +From 91a1b0955a053f73e6d531f0f12eaa604aca79d7 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 19 May 2022 16:35:28 +0200 +Subject: [PATCH 80/99] CVE-2022-2031 testprogs: Add kadmin/changepw + canonicalization test with MIT kpasswd + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton +--- + selftest/knownfail.d/kadmin_changepw | 1 + + testprogs/blackbox/test_kpasswd_heimdal.sh | 35 +++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + create mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git a/selftest/knownfail.d/kadmin_changepw b/selftest/knownfail.d/kadmin_changepw +new file mode 100644 +index 00000000000..97c14793ea5 +--- /dev/null ++++ b/selftest/knownfail.d/kadmin_changepw +@@ -0,0 +1 @@ ++^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git a/testprogs/blackbox/test_kpasswd_heimdal.sh b/testprogs/blackbox/test_kpasswd_heimdal.sh +index 1e895daa162..059b7a8e4d1 100755 +--- a/testprogs/blackbox/test_kpasswd_heimdal.sh ++++ b/testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -7,7 +7,7 @@ + + if [ $# -lt 6 ]; then + cat < "${PREFIX}/tmpkpasswdscript" < "${KRB5_CONFIG}" ++ testit "MIT kpasswd change user password" \ ++ "${texpect}" "${PREFIX}/tmpkpasswdscript" "${mit_kpasswd}" \ ++ "${TEST_PRINCIPAL}" || ++ failed=$((failed + 1)) ++ KRB5_CONFIG="${SAVE_KRB5_CONFIG}" ++ export KRB5_CONFIG ++fi ++ ++TEST_PASSWORD="${TEST_PASSWORD_NEW}" ++TEST_PASSWORD_NEW="testPaSS@03force%" ++ + ########################################################### + ### Force password change at login + ########################################################### +-- +2.25.1 diff --git a/backport-0036-CVE-2022-2031-CVE-2022-32744.patch b/backport-0036-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0afdab3aa4d02b080a5bb4058b4ce48ec911fd0 --- /dev/null +++ b/backport-0036-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,52 @@ +From 36d94ffb9c99f3e515024424020e3e03e98f34f5 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 09:54:18 +0200 +Subject: [PATCH 81/99] CVE-2022-2031 s4:kdc: Implement is_kadmin_changepw() + helper function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton + +[jsutton@samba.org Adapted entry to entry_ex->entry] +--- + source4/kdc/db-glue.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 5752ffb821c..45159e6e64d 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -816,6 +816,14 @@ static int principal_comp_strcmp(krb5_context context, + component, string, false); + } + ++static bool is_kadmin_changepw(krb5_context context, ++ krb5_const_principal principal) ++{ ++ return krb5_princ_size(context, principal) == 2 && ++ (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) && ++ (principal_comp_strcmp(context, principal, 1, "changepw") == 0); ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -1110,11 +1118,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + * 'change password', as otherwise we could get into + * trouble, and not enforce the password expirty. + * Instead, only do it when request is for the kpasswd service */ +- if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER +- && krb5_princ_size(context, principal) == 2 +- && (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) +- && (principal_comp_strcmp(context, principal, 1, "changepw") == 0) +- && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && ++ is_kadmin_changepw(context, principal) && ++ lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { + entry_ex->entry.flags.change_pw = 1; + } + +-- +2.25.1 diff --git a/backport-0037-CVE-2022-2031-CVE-2022-32744.patch b/backport-0037-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..b17b92a1cef2af4cc2ba1210db49f43dcae439cd --- /dev/null +++ b/backport-0037-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,239 @@ +From f68877af829bf73da8e965c9458a9846d1757038 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 82/99] CVE-2022-2031 s4:kdc: Split out a + samba_kdc_get_entry_principal() function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry] + +[jsutton@samba.org Fixed conflicts caused by superfluous whitespace] +--- + source4/kdc/db-glue.c | 192 +++++++++++++++++++++++------------------- + 1 file changed, 107 insertions(+), 85 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 45159e6e64d..ac0c206b5c1 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -824,6 +824,101 @@ static bool is_kadmin_changepw(krb5_context context, + (principal_comp_strcmp(context, principal, 1, "changepw") == 0); + } + ++static krb5_error_code samba_kdc_get_entry_principal( ++ krb5_context context, ++ struct samba_kdc_db_context *kdc_db_ctx, ++ const char *samAccountName, ++ enum samba_kdc_ent_type ent_type, ++ unsigned flags, ++ krb5_const_principal in_princ, ++ krb5_principal *out_princ) ++{ ++ struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; ++ krb5_error_code ret = 0; ++ ++ /* ++ * If we are set to canonicalize, we get back the fixed UPPER ++ * case realm, and the real username (ie matching LDAP ++ * samAccountName) ++ * ++ * Otherwise, if we are set to enterprise, we ++ * get back the whole principal as-sent ++ * ++ * Finally, if we are not set to canonicalize, we get back the ++ * fixed UPPER case realm, but the as-sent username ++ */ ++ ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, ++ lpcfg_realm(lp_ctx), "krbtgt", ++ lpcfg_realm(lp_ctx), NULL); ++ if (ret) { ++ return ret; ++ } ++ smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ /* ++ * this appears to be required regardless of ++ * the canonicalize flag from the client ++ */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -913,93 +1008,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + userAccountControl |= msDS_User_Account_Control_Computed; + } + +- /* +- * If we are set to canonicalize, we get back the fixed UPPER +- * case realm, and the real username (ie matching LDAP +- * samAccountName) +- * +- * Otherwise, if we are set to enterprise, we +- * get back the whole principal as-sent +- * +- * Finally, if we are not set to canonicalize, we get back the +- * fixed UPPER case realm, but the as-sent username +- */ +- + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; +- +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- smb_krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } +- +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } + } + + /* First try and figure out the flags based on the userAccountControl */ +@@ -1185,6 +1195,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + } + } + ++ ret = samba_kdc_get_entry_principal(context, ++ kdc_db_ctx, ++ samAccountName, ++ ent_type, ++ flags, ++ principal, ++ &entry_ex->entry.principal); ++ if (ret != 0) { ++ krb5_clear_error_message(context); ++ goto out; ++ } ++ + entry_ex->entry.valid_start = NULL; + + entry_ex->entry.max_life = malloc(sizeof(*entry_ex->entry.max_life)); +-- +2.25.1 diff --git a/backport-0038-CVE-2022-2031-CVE-2022-32744.patch b/backport-0038-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..65e34cc08166c3b9c3fa34440ea7da2274b8c492 --- /dev/null +++ b/backport-0038-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,162 @@ +From fa4742e1b9dea0b9c379f00666478bd41c021634 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 17:19:58 +1200 +Subject: [PATCH 83/99] CVE-2022-2031 s4:kdc: Refactor + samba_kdc_get_entry_principal() + +This eliminates some duplicate branches. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider +--- + source4/kdc/db-glue.c | 116 ++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 61 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index ac0c206b5c1..385c118a073 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -834,7 +834,8 @@ static krb5_error_code samba_kdc_get_entry_principal( + krb5_principal *out_princ) + { + struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; +- krb5_error_code ret = 0; ++ krb5_error_code code = 0; ++ bool canon = flags & (SDB_F_CANON|SDB_F_FORCE_CANON); + + /* + * If we are set to canonicalize, we get back the fixed UPPER +@@ -848,75 +849,68 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, out_princ, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- return ret; +- } +- smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } +- } ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ return 0; ++ } ++ ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. + * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. + */ +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } ++ /* ++ * For a krbtgt entry, this appears to be required regardless of the ++ * canonicalize flag from the client. ++ */ ++ code = krb5_copy_principal(context, in_princ, out_princ); ++ if (code != 0) { ++ return code; + } + +- return 0; ++ /* ++ * While we have copied the client principal, tests show that Win2k3 ++ * returns the 'corrected' realm, not the client-specified realm. This ++ * code attempts to replace the client principal's realm with the one ++ * we determine from our records ++ */ ++ code = smb_krb5_principal_set_realm(context, ++ *out_princ, ++ lpcfg_realm(lp_ctx)); ++ ++ return code; + } + + /* +-- +2.25.1 diff --git a/backport-0039-CVE-2022-2031-CVE-2022-32744.patch b/backport-0039-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..571f8e1dfd3f5358e0ebe7111197761265713732 --- /dev/null +++ b/backport-0039-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,150 @@ +From 3cab62893668742781551dae6505558e47cf08b5 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 84/99] CVE-2022-2031 s4:kdc: Fix canonicalisation of + kadmin/changepw principal + +Since this principal goes through the samba_kdc_fetch_server() path, +setting the canonicalisation flag would cause the principal to be +replaced with the sAMAccountName; this meant requests to +kadmin/changepw@REALM would result in a ticket to krbtgt@REALM. Now we +properly handle canonicalisation for the kadmin/changepw principal. + +View with 'git show -b'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Andreas Schneider +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; removed MIT KDC + 1.20-specific knownfails] +Conflict: remove selftest/knownfail_heimdal_kdc +--- + selftest/knownfail.d/kadmin_changepw | 1 - + source4/kdc/db-glue.c | 84 +++++++++++++++------------- + 3 files changed, 46 insertions(+), 41 deletions(-) + delete mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git a/selftest/knownfail.d/kadmin_changepw b/selftest/knownfail.d/kadmin_changepw +deleted file mode 100644 +index 97c14793ea5..00000000000 +--- a/selftest/knownfail.d/kadmin_changepw ++++ /dev/null +@@ -1 +0,0 @@ +-^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 385c118a073..d2d7136608e 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -830,6 +830,7 @@ static krb5_error_code samba_kdc_get_entry_principal( + const char *samAccountName, + enum samba_kdc_ent_type ent_type, + unsigned flags, ++ bool is_kadmin_changepw, + krb5_const_principal in_princ, + krb5_principal *out_princ) + { +@@ -849,46 +850,52 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- "krbtgt", +- lpcfg_realm(lp_ctx), +- NULL); +- if (code != 0) { +- return code; +- } +- smb_krb5_principal_set_type(context, +- *out_princ, +- KRB5_NT_SRV_INST); ++ /* ++ * We need to ensure that the kadmin/changepw principal isn't able to ++ * issue krbtgt tickets, even if canonicalization is turned on. ++ */ ++ if (!is_kadmin_changepw) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- return 0; +- } ++ return 0; ++ } + +- if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || +- (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the +- * AS-REQ case. +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that +- * wants the canonical name in all lookups, and takes +- * care to canonicalize only when appropriate. +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- samAccountName, +- NULL); +- return code; ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + } + + /* +@@ -1194,6 +1201,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + samAccountName, + ent_type, + flags, ++ entry_ex->entry.flags.change_pw, + principal, + &entry_ex->entry.principal); + if (ret != 0) { +-- +2.25.1 diff --git a/backport-0040-CVE-2022-2031-CVE-2022-32744.patch b/backport-0040-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..a7e2dc6ee7cc22f283c471935c04892efe7dabba --- /dev/null +++ b/backport-0040-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,70 @@ +From 531e7b596d35785bee61f3b4289e38ece1530f94 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 17:53:49 +1200 +Subject: [PATCH 85/99] CVE-2022-2031 s4:kdc: Limit kpasswd ticket lifetime to + two minutes or less + +This matches the behaviour of Windows. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; included + samba_kdc.h header file] + +[jsutton@samba.org Fixed conflicts] +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/db-glue.c | 5 +++++ + source4/kdc/mit-kdb/kdb_samba_principals.c | 2 +- + source4/kdc/samba_kdc.h | 2 ++ + 5 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index d2d7136608e..073ec83c8cf 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -1226,6 +1226,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + kdc_db_ctx->policy.usr_tkt_lifetime); + } + ++ if (entry_ex->entry.flags.change_pw) { ++ /* Limit lifetime of kpasswd tickets to two minutes or less. */ ++ *entry_ex->entry.max_life = MIN(*entry_ex->entry.max_life, CHANGEPW_LIFETIME); ++ } ++ + entry_ex->entry.max_renew = malloc(sizeof(*entry_ex->entry.max_life)); + if (entry_ex->entry.max_renew == NULL) { + ret = ENOMEM; +diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c +index cc67c2392be..2059ffa855e 100644 +--- a/source4/kdc/mit-kdb/kdb_samba_principals.c ++++ b/source4/kdc/mit-kdb/kdb_samba_principals.c +@@ -27,11 +27,11 @@ + #include + #include + ++#include "kdc/samba_kdc.h" + #include "kdc/mit_samba.h" + #include "kdb_samba.h" + + #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ +-#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ + + krb5_error_code ks_get_principal(krb5_context context, + krb5_const_principal principal, +diff --git a/source4/kdc/samba_kdc.h b/source4/kdc/samba_kdc.h +index e228a82ce6a..8010d7c35ed 100644 +--- a/source4/kdc/samba_kdc.h ++++ b/source4/kdc/samba_kdc.h +@@ -62,4 +62,6 @@ struct samba_kdc_entry { + + extern struct hdb_method hdb_samba4_interface; + ++#define CHANGEPW_LIFETIME 60*2 /* 2 minutes */ ++ + #endif /* _SAMBA_KDC_H_ */ +-- +2.25.1 diff --git a/backport-0041-CVE-2022-2031-CVE-2022-32744.patch b/backport-0041-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..19e22522243e1390e980a6d668a27859be69a6fe --- /dev/null +++ b/backport-0041-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,78 @@ +From d40593be83144713cfc43e4eb1c7bc2d925a0da0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 20:00:55 +1200 +Subject: [PATCH 88/99] CVE-2022-2031 s4:kdc: Don't use strncmp to compare + principal components + +We would only compare the first 'n' characters, where 'n' is the length +of the principal component string, so 'k@REALM' would erroneously be +considered equal to 'krbtgt@REALM'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/db-glue.c | 27 ++++++++++++++++++++++----- + 3 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 073ec83c8cf..cfa2097acbd 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -769,15 +769,19 @@ static int principal_comp_strcmp_int(krb5_context context, + bool do_strcasecmp) + { + const char *p; +- size_t len; + + #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) + p = krb5_principal_get_comp_string(context, principal, component); + if (p == NULL) { + return -1; + } +- len = strlen(p); ++ if (do_strcasecmp) { ++ return strcasecmp(p, string); ++ } else { ++ return strcmp(p, string); ++ } + #else ++ size_t len; + krb5_data *d; + if (component >= krb5_princ_size(context, principal)) { + return -1; +@@ -789,13 +793,26 @@ static int principal_comp_strcmp_int(krb5_context context, + } + + p = d->data; +- len = d->length; +-#endif ++ ++ len = strlen(string); ++ ++ /* ++ * We explicitly return -1 or 1. Subtracting of the two lengths might ++ * give the wrong result if the result overflows or loses data when ++ * narrowed to int. ++ */ ++ if (d->length < len) { ++ return -1; ++ } else if (d->length > len) { ++ return 1; ++ } ++ + if (do_strcasecmp) { + return strncasecmp(p, string, len); + } else { +- return strncmp(p, string, len); ++ return memcmp(p, string, len); + } ++#endif + } + + static int principal_comp_strcasecmp(krb5_context context, +-- +2.25.1 diff --git a/backport-0042-CVE-2022-2031-CVE-2022-32744.patch b/backport-0042-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..abb48b3a52aa416a28729f60412799e604bb9515 --- /dev/null +++ b/backport-0042-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,79 @@ +From 42ba919c06c24c42ef123304de0c2ca8c689591a Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:36:30 +1200 +Subject: [PATCH 89/99] CVE-2022-32744 s4:kdc: Rename keytab_name -> + kpasswd_keytab_name + +This makes explicitly clear the purpose of this keytab. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to lacking HDBGET support] +--- + source4/kdc/kdc-heimdal.c | 4 ++-- + source4/kdc/kdc-server.h | 2 +- + source4/kdc/kdc-service-mit.c | 4 ++-- + source4/kdc/kpasswd-service.c | 2 +- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c +index ba74df4f2ec..a4c845b62f8 100644 +--- a/source4/kdc/kdc-heimdal.c ++++ b/source4/kdc/kdc-heimdal.c +@@ -444,8 +444,8 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) + return; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "kdc: Failed to set keytab name", + true); +diff --git a/source4/kdc/kdc-server.h b/source4/kdc/kdc-server.h +index fd883c2e4b4..89b30f122f5 100644 +--- a/source4/kdc/kdc-server.h ++++ b/source4/kdc/kdc-server.h +@@ -40,7 +40,7 @@ struct kdc_server { + struct ldb_context *samdb; + bool am_rodc; + uint32_t proxy_timeout; +- const char *keytab_name; ++ const char *kpasswd_keytab_name; + void *private_data; + }; + +diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c +index 5d4180aa7cc..22663b6ecc8 100644 +--- a/source4/kdc/kdc-service-mit.c ++++ b/source4/kdc/kdc-service-mit.c +@@ -291,8 +291,8 @@ NTSTATUS mitkdc_task_init(struct task_server *task) + return NT_STATUS_INTERNAL_ERROR; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "KDB:"); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "KDB:"); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "KDC: Out of memory", + true); +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index b4706de1ad7..0d2acd8d9e8 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -167,7 +167,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, +- kdc->keytab_name, ++ kdc->kpasswd_keytab_name, + CRED_SPECIFIED); + if (rv != 0) { + DBG_ERR("Failed to set credentials keytab name\n"); +-- +2.25.1 diff --git a/backport-0043-CVE-2022-2031-CVE-2022-32744.patch b/backport-0043-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..b4cb10b9f32d0d7520caa8f257bb3f45a90e1549 --- /dev/null +++ b/backport-0043-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,76 @@ +From 997f50c66471071efb8e02d8efbe4bf5d932e7ee Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 8 Jun 2022 13:53:29 +1200 +Subject: [PATCH 90/99] s4:kdc: Remove kadmin mode from HDB plugin + +It appears we no longer require it. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/hdb-samba4-plugin.c | 35 +++++++-------------------------- + 1 file changed, 7 insertions(+), 28 deletions(-) + +diff --git a/source4/kdc/hdb-samba4-plugin.c b/source4/kdc/hdb-samba4-plugin.c +index 6f76124995d..4b90a766f76 100644 +--- a/source4/kdc/hdb-samba4-plugin.c ++++ b/source4/kdc/hdb-samba4-plugin.c +@@ -21,40 +21,20 @@ + + #include "includes.h" + #include "kdc/kdc-glue.h" +-#include "kdc/db-glue.h" +-#include "lib/util/samba_util.h" + #include "lib/param/param.h" +-#include "source4/lib/events/events.h" + + static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, const char *arg) + { + NTSTATUS nt_status; +- void *ptr; +- struct samba_kdc_base_context *base_ctx; +- +- if (sscanf(arg, "&%p", &ptr) == 1) { +- base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); +- } else if (arg[0] == '\0' || file_exist(arg)) { +- /* This mode for use in kadmin, rather than in Samba */ +- +- setup_logging("hdb_samba4", DEBUG_DEFAULT_STDERR); +- +- base_ctx = talloc_zero(NULL, struct samba_kdc_base_context); +- if (!base_ctx) { +- return ENOMEM; +- } +- +- base_ctx->ev_ctx = s4_event_context_init(base_ctx); +- base_ctx->lp_ctx = loadparm_init_global(false); +- if (arg[0]) { +- lpcfg_load(base_ctx->lp_ctx, arg); +- } else { +- lpcfg_load_default(base_ctx->lp_ctx); +- } +- } else { ++ void *ptr = NULL; ++ struct samba_kdc_base_context *base_ctx = NULL; ++ ++ if (sscanf(arg, "&%p", &ptr) != 1) { + return EINVAL; + } + ++ 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); + +@@ -90,8 +70,7 @@ static void hdb_samba4_fini(void *ctx) + + /* Only used in the hdb-backed keytab code + * for a keytab of 'samba4&
' or samba4, to find +- * kpasswd's key in the main DB, and to +- * copy all the keys into a file (libnet_keytab_export) ++ * kpasswd's key in the main DB + * + * The
is the string form of a pointer to a talloced struct hdb_samba_context + */ +-- +2.25.1 diff --git a/backport-0044-CVE-2022-2031-CVE-2022-32744.patch b/backport-0044-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..15ba87beedce2e985ea4d8c22410f140b52a711e --- /dev/null +++ b/backport-0044-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,146 @@ +From c0c4b7a4bd229bd36d586faec6249baaba8e7adc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:39:20 +1200 +Subject: [PATCH 91/99] 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] +Conlict: remove selftest/knownfail_heimdal_kdc +--- + 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/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, +-- +2.25.1 diff --git a/backport-0045-CVE-2022-2031-CVE-2022-32744.patch b/backport-0045-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..7ba648ef2ce6fb90e9455a4fdf3bb87597621aba --- /dev/null +++ b/backport-0045-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,86 @@ +From 340181bc1100fa31c63af88214a3d8328b944fe9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:16:02 +1200 +Subject: [PATCH 92/99] CVE-2022-32744 s4:kpasswd: Ensure we pass the kpasswd + server principal into krb5_rd_req_ctx() + +To ensure that, when decrypting the kpasswd ticket, we look up the +correct principal and don't trust the sname from the ticket, we should +pass the principal name of the kpasswd service into krb5_rd_req_ctx(). +However, gensec_krb5_update_internal() will pass in NULL unless the +principal in our credentials is CRED_SPECIFIED. + +At present, our principal will be considered obtained as CRED_SMB_CONF +(from the cli_credentials_set_conf() a few lines up), so we explicitly +set the realm again, but this time as CRED_SPECIFIED. Now the value of +server_in_keytab that we provide to smb_krb5_rd_req_decoded() will not +be NULL. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed knownfail as KDC no longer panics] +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/kpasswd-service.c | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index 0d2acd8d9e8..b6400be0c49 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -29,6 +29,7 @@ + #include "kdc/kdc-server.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "param/param.h" + + #define HEADER_LEN 6 + #ifndef RFC3244_VERSION +@@ -158,6 +159,20 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + + cli_credentials_set_conf(server_credentials, kdc->task->lp_ctx); + ++ /* ++ * After calling cli_credentials_set_conf(), explicitly set the realm ++ * with CRED_SPECIFIED. We need to do this so the result of ++ * principal_from_credentials() called from the gensec layer is ++ * CRED_SPECIFIED rather than CRED_SMB_CONF, avoiding a fallback to ++ * match-by-key (very undesirable in this case). ++ */ ++ ok = cli_credentials_set_realm(server_credentials, ++ lpcfg_realm(kdc->task->lp_ctx), ++ CRED_SPECIFIED); ++ if (!ok) { ++ goto done; ++ } ++ + ok = cli_credentials_set_username(server_credentials, + "kadmin/changepw", + CRED_SPECIFIED); +@@ -165,6 +180,21 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + goto done; + } + ++ /* Check that the server principal is indeed CRED_SPECIFIED. */ ++ { ++ char *principal = NULL; ++ enum credentials_obtained obtained; ++ ++ principal = cli_credentials_get_principal_and_obtained(server_credentials, ++ tmp_ctx, ++ &obtained); ++ if (obtained < CRED_SPECIFIED) { ++ goto done; ++ } ++ ++ TALLOC_FREE(principal); ++ } ++ + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, + kdc->kpasswd_keytab_name, +-- +2.25.1 diff --git a/backport-0046-CVE-2022-2031-CVE-2022-32744.patch b/backport-0046-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..f08df37a4acac4b49c3c4fb26f47c4f8fe24cc02 --- /dev/null +++ b/backport-0046-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,171 @@ +From 4b61092459b403b2945daa9082052366f3508b69 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:07 +1200 +Subject: [PATCH 94/99] CVE-2022-2031 auth: Add ticket type field to + auth_user_info_dc and auth_session_info + +This field may be used to convey whether we were provided with a TGT or +a non-TGT. We ensure both structures are zeroed out to avoid incorrect +results being produced by an uninitialised field. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + auth/auth_sam_reply.c | 2 +- + auth/auth_util.c | 2 +- + librpc/idl/auth.idl | 23 +++++++++++++++++++++++ + source4/auth/ntlm/auth_developer.c | 2 +- + source4/auth/sam.c | 2 +- + source4/auth/session.c | 2 ++ + source4/auth/system_session.c | 6 +++--- + 7 files changed, 32 insertions(+), 7 deletions(-) + +diff --git a/auth/auth_sam_reply.c b/auth/auth_sam_reply.c +index b5b6362dc93..2e27e5715d1 100644 +--- a/auth/auth_sam_reply.c ++++ b/auth/auth_sam_reply.c +@@ -416,7 +416,7 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx, + return NT_STATUS_INVALID_LEVEL; + } + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* +diff --git a/auth/auth_util.c b/auth/auth_util.c +index fe01babd107..ec9094d0f15 100644 +--- a/auth/auth_util.c ++++ b/auth/auth_util.c +@@ -44,7 +44,7 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + return NULL; + } + +- dst = talloc(mem_ctx, struct auth_session_info); ++ dst = talloc_zero(mem_ctx, struct auth_session_info); + if (dst == NULL) { + DBG_ERR("talloc failed\n"); + TALLOC_FREE(frame); +diff --git a/librpc/idl/auth.idl b/librpc/idl/auth.idl +index 1092935b971..f7658cdde28 100644 +--- a/librpc/idl/auth.idl ++++ b/librpc/idl/auth.idl +@@ -75,6 +75,26 @@ interface auth + [unique,charset(UTF8),string] char *sanitized_username; + } auth_user_info_unix; + ++ /* ++ * If the user was authenticated with a Kerberos ticket, this indicates ++ * the type of the ticket; TGT, or non-TGT (i.e. service ticket). If ++ * unset, the type is unknown. This indicator is useful for the KDC and ++ * the kpasswd service, which share the same account and keys. By ++ * ensuring it is provided with the appopriate ticket type, each service ++ * avoids accepting a ticket meant for the other. ++ * ++ * The heuristic used to determine the type is the presence or absence ++ * of a REQUESTER_SID buffer in the PAC; we use its presence to assume ++ * we have a TGT. This heuristic will fail for older Samba versions and ++ * Windows prior to Nov. 2021 updates, which lack support for this ++ * buffer. ++ */ ++ typedef enum { ++ TICKET_TYPE_UNKNOWN = 0, ++ TICKET_TYPE_TGT = 1, ++ TICKET_TYPE_NON_TGT = 2 ++ } ticket_type; ++ + /* This is the interim product of the auth subsystem, before + * privileges and local groups are handled */ + typedef [public] struct { +@@ -83,6 +103,7 @@ interface auth + auth_user_info *info; + [noprint] DATA_BLOB user_session_key; + [noprint] DATA_BLOB lm_session_key; ++ ticket_type ticket_type; + } auth_user_info_dc; + + typedef [public] struct { +@@ -112,6 +133,8 @@ interface auth + * We generate this in auth_generate_session_info() + */ + GUID unique_session_token; ++ ++ ticket_type ticket_type; + } auth_session_info; + + typedef [public] struct { +diff --git a/source4/auth/ntlm/auth_developer.c b/source4/auth/ntlm/auth_developer.c +index 1823989c68d..6e92252d5c5 100644 +--- a/source4/auth/ntlm/auth_developer.c ++++ b/source4/auth/ntlm/auth_developer.c +@@ -76,7 +76,7 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, + } + NT_STATUS_NOT_OK_RETURN(nt_status); + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +diff --git a/source4/auth/sam.c b/source4/auth/sam.c +index 8b233bab3ad..7c609655fcb 100644 +--- a/source4/auth/sam.c ++++ b/source4/auth/sam.c +@@ -363,7 +363,7 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx, + TALLOC_CTX *tmp_ctx; + struct ldb_message_element *el; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + tmp_ctx = talloc_new(user_info_dc); +diff --git a/source4/auth/session.c b/source4/auth/session.c +index 8e44dcd24f1..d6e936dd1f1 100644 +--- a/source4/auth/session.c ++++ b/source4/auth/session.c +@@ -222,6 +222,8 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, + + session_info->credentials = NULL; + ++ session_info->ticket_type = user_info_dc->ticket_type; ++ + talloc_steal(mem_ctx, session_info); + *_session_info = session_info; + talloc_free(tmp_ctx); +diff --git a/source4/auth/system_session.c b/source4/auth/system_session.c +index 85b8f1c4edb..2518d654e8b 100644 +--- a/source4/auth/system_session.c ++++ b/source4/auth/system_session.c +@@ -115,7 +115,7 @@ NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +@@ -191,7 +191,7 @@ static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + user_info_dc->num_sids = 7; +@@ -356,7 +356,7 @@ _PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx, + { + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +-- +2.25.1 diff --git a/backport-0047-CVE-2022-2031-CVE-2022-32744.patch b/backport-0047-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..c6764bfa61c92c88451ab9d6f4dd325fc4bb679e --- /dev/null +++ b/backport-0047-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,83 @@ +From 89c6e36938c27b572573b06d1b35db210bfda99b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:35 +1200 +Subject: [PATCH 95/99] CVE-2022-2031 s4:auth: Use PAC to determine whether + ticket is a TGT + +We use the presence or absence of a REQUESTER_SID PAC buffer to +determine whether the ticket is a TGT. We will later use this to reject +TGTs where a service ticket is expected. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/kerberos/kerberos_pac.c | 44 ++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c +index 54ef4d61b02..bd0ae20e007 100644 +--- a/source4/auth/kerberos/kerberos_pac.c ++++ b/source4/auth/kerberos/kerberos_pac.c +@@ -282,6 +282,28 @@ + return ret; + } + ++static krb5_error_code kerberos_pac_buffer_present(krb5_context context, ++ const krb5_pac pac, ++ uint32_t type) ++{ ++#ifdef SAMBA4_USES_HEIMDAL ++ return krb5_pac_get_buffer(context, pac, type, NULL); ++#else /* MIT */ ++ krb5_error_code ret; ++ krb5_data data; ++ ++ /* ++ * MIT won't let us pass NULL for the data parameter, so we are forced ++ * to allocate a new buffer and then immediately free it. ++ */ ++ ret = krb5_pac_get_buffer(context, pac, type, &data); ++ if (ret == 0) { ++ krb5_free_data_contents(context, &data); ++ } ++ return ret; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} ++ + krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + krb5_pac pac, + krb5_context context, +@@ -414,6 +436,28 @@ krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + return EINVAL; + } + } ++ ++ /* ++ * Based on the presence of a REQUESTER_SID PAC buffer, ascertain ++ * whether the ticket is a TGT. This helps the KDC and kpasswd service ++ * ensure they do not accept tickets meant for the other. ++ * ++ * This heuristic will fail for older Samba versions and Windows prior ++ * to Nov. 2021 updates, which lack support for the REQUESTER_SID PAC ++ * buffer. ++ */ ++ ret = kerberos_pac_buffer_present(context, pac, PAC_TYPE_REQUESTER_SID); ++ if (ret == ENOENT) { ++ /* This probably isn't a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_NON_TGT; ++ } else if (ret != 0) { ++ talloc_free(tmp_ctx); ++ return ret; ++ } else { ++ /* This probably is a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_TGT; ++ } ++ + *user_info_dc = user_info_dc_out; + + return 0; +-- +2.25.1 diff --git a/backport-0048-CVE-2022-2031-CVE-2022-32744.patch b/backport-0048-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..df2a992cf79fba5e939cc3863c19fc4abd9bf3ea --- /dev/null +++ b/backport-0048-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,136 @@ +From d5af460403d3949ba266f5c74f051247cd7ce752 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:53 +1200 +Subject: [PATCH 96/99] CVE-2022-2031 s4:kpasswd: Do not accept TGTs as kpasswd + tickets + +If TGTs can be used as kpasswd tickets, the two-minute lifetime of a +authentic kpasswd ticket may be bypassed. Furthermore, kpasswd tickets +are not supposed to be cached, but using this flaw, a stolen credentials +cache containing a TGT may be used to change that account's password, +and thus is made more valuable to an attacker. + +Since all TGTs should be issued with a REQUESTER_SID PAC buffer, and +service tickets without it, we assert the absence of this buffer to +ensure we're not accepting a TGT. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Fixed knownfail conflicts] +Conflict: remove selftest/knownfail_heimdal_kdc selftest/knownfail_mit_kdc +--- + source4/kdc/kpasswd-helper.c | 20 ++++++++++++++++++++ + source4/kdc/kpasswd-helper.h | 2 ++ + source4/kdc/kpasswd-service-heimdal.c | 13 +++++++++++++ + source4/kdc/kpasswd-service-mit.c | 13 +++++++++++++ + 6 files changed, 48 insertions(+), 8 deletions(-) + +diff --git a/source4/kdc/kpasswd-helper.c b/source4/kdc/kpasswd-helper.c +index 55a2f5b3bf6..2ffdb79aea5 100644 +--- a/source4/kdc/kpasswd-helper.c ++++ b/source4/kdc/kpasswd-helper.c +@@ -241,3 +241,23 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + + return status; + } ++ ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string) ++{ ++ switch(session_info->ticket_type) { ++ case TICKET_TYPE_TGT: ++ /* TGTs are disallowed here. */ ++ *error_string = "A TGT may not be used as a ticket to kpasswd"; ++ return KRB5_KPASSWD_AUTHERROR; ++ case TICKET_TYPE_NON_TGT: ++ /* Non-TGTs are permitted, and expected. */ ++ break; ++ default: ++ /* In case we forgot to set the type. */ ++ *error_string = "Failed to ascertain that ticket to kpasswd is not a TGT"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ ++ return 0; ++} +diff --git a/source4/kdc/kpasswd-helper.h b/source4/kdc/kpasswd-helper.h +index 8fad81e0a5d..94a6e2acfdd 100644 +--- a/source4/kdc/kpasswd-helper.h ++++ b/source4/kdc/kpasswd-helper.h +@@ -43,4 +43,6 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + enum samPwdChangeReason *reject_reason, + struct samr_DomInfo1 **dominfo); + ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string); + #endif /* _KPASSWD_HELPER_H */ +diff --git a/source4/kdc/kpasswd-service-heimdal.c b/source4/kdc/kpasswd-service-heimdal.c +index a0352d1ad35..4d009b9eb24 100644 +--- a/source4/kdc/kpasswd-service-heimdal.c ++++ b/source4/kdc/kpasswd-service-heimdal.c +@@ -253,6 +253,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -264,6 +265,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case KRB5_KPASSWD_VERS_CHANGEPW: { + DATA_BLOB password = data_blob_null; +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index de4c6f3f622..6b051567b6e 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -332,6 +332,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -344,6 +345,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case 1: { + DATA_BLOB password; +-- +2.25.1 diff --git a/backport-0049-CVE-2022-2031-CVE-2022-32744.patch b/backport-0049-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..410057765dd4e967cf731ee82222eed2c7d42f34 --- /dev/null +++ b/backport-0049-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,43 @@ +From a6231af1f1c03cd81614332f867916e1748e03a8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 23 Jun 2022 13:59:11 +1200 +Subject: [PATCH 97/99] CVE-2022-2031 testprogs: Add test for short-lived + ticket across an incoming trust + +We ensure that the KDC does not reject a TGS-REQ with our short-lived +TGT over an incoming trust. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton + +[jsutton@samba.org Changed --use-krb5-ccache to -k yes to match + surrounding usage] +--- + testprogs/blackbox/test_kinit_trusts_heimdal.sh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/testprogs/blackbox/test_kinit_trusts_heimdal.sh b/testprogs/blackbox/test_kinit_trusts_heimdal.sh +index bf0b81a0473..621434eac35 100755 +--- a/testprogs/blackbox/test_kinit_trusts_heimdal.sh ++++ b/testprogs/blackbox/test_kinit_trusts_heimdal.sh +@@ -54,6 +54,10 @@ testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppa + test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" -k yes || failed=`expr $failed + 1` + rm -rf $KRB5CCNAME_PATH + ++testit "kinit with password and two minute lifetime" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac --server=krbtgt/$REALM@$TRUST_REALM --lifetime=2m $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` ++test_smbclient "Test login with user kerberos ccache and two minute lifetime" 'ls' "$unc" -k yes || failed=`expr $failed + 1` ++rm -rf $KRB5CCNAME_PATH ++ + # Test with smbclient4 + smbclient="$samba4bindir/smbclient4" + testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` +@@ -94,5 +98,5 @@ testit "wbinfo check outgoing trust pw" $VALGRIND $wbinfo --check-secret --domai + + test_smbclient "Test user login with the changed outgoing secret" 'ls' "$unc" -k yes -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1` + +-rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache ++rm -f $PREFIX/tmpccache $PREFIX/tmppassfile + exit $failed +-- +2.25.1 diff --git a/backport-0050-CVE-2022-2031-CVE-2022-32744.patch b/backport-0050-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..7931ff7ef75ab5f5e33c74b817a4da97b8ed0220 --- /dev/null +++ b/backport-0050-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,39 @@ +From 6acbb94daddb94a795e0b506bb7637ed15578cc5 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 1 Sep 2021 15:39:19 +1200 +Subject: [PATCH] krb5pac.idl: Add ticket checksum PAC buffer type + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +Reviewed-by: Isaac Boukris +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14881 +(cherry picked from commit ff2f38fae79220e16765e17671972f9a55eb7cce) +--- + librpc/idl/krb5pac.idl | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl +index fb360c1257f..3239d7656b6 100644 +--- a/librpc/idl/krb5pac.idl ++++ b/librpc/idl/krb5pac.idl +@@ -112,7 +112,8 @@ interface krb5pac + PAC_TYPE_KDC_CHECKSUM = 7, + PAC_TYPE_LOGON_NAME = 10, + PAC_TYPE_CONSTRAINED_DELEGATION = 11, +- PAC_TYPE_UPN_DNS_INFO = 12 ++ PAC_TYPE_UPN_DNS_INFO = 12, ++ PAC_TYPE_TICKET_CHECKSUM = 16 + } PAC_TYPE; + + typedef struct { +@@ -128,6 +129,7 @@ interface krb5pac + [case(PAC_TYPE_CONSTRAINED_DELEGATION)][subcontext(0xFFFFFC01)] + PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation; + [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; ++ [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; + /* when new PAC info types are added they are supposed to be done + in such a way that they are backwards compatible with existing + servers. This makes it safe to just use a [default] for +-- +2.33.0 + diff --git a/backport-0051-CVE-2022-2031-CVE-2022-32744.patch b/backport-0051-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..eacd69951dcf208a9793ec3291e506bdb872e6c3 --- /dev/null +++ b/backport-0051-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,56 @@ +From c22162544b70c5e546d973506cdb3ca197bdb375 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 26 Oct 2021 20:33:38 +1300 +Subject: [PATCH] CVE-2020-25719 krb5pac.idl: Add PAC_ATTRIBUTES_INFO PAC + buffer type + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +--- + librpc/idl/krb5pac.idl | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl +index aaa982b..01af1d0 100644 +--- a/librpc/idl/krb5pac.idl ++++ b/librpc/idl/krb5pac.idl +@@ -111,6 +111,16 @@ interface krb5pac + [switch_is(flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID)] PAC_UPN_DNS_INFO_EX ex; + } PAC_UPN_DNS_INFO; + ++ typedef [bitmap32bit] bitmap { ++ PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED = 0x00000001, ++ PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY = 0x00000002 ++ } PAC_ATTRIBUTE_INFO_FLAGS; ++ ++ typedef struct { ++ uint32 flags_length; /* length in bits */ ++ PAC_ATTRIBUTE_INFO_FLAGS flags; ++ } PAC_ATTRIBUTES_INFO; ++ + typedef [public] struct { + PAC_LOGON_INFO *info; + } PAC_LOGON_INFO_CTR; +@@ -127,7 +137,8 @@ interface krb5pac + PAC_TYPE_LOGON_NAME = 10, + PAC_TYPE_CONSTRAINED_DELEGATION = 11, + PAC_TYPE_UPN_DNS_INFO = 12, +- PAC_TYPE_TICKET_CHECKSUM = 16 ++ PAC_TYPE_TICKET_CHECKSUM = 16, ++ PAC_TYPE_ATTRIBUTES_INFO = 17 + } PAC_TYPE; + + typedef struct { +@@ -144,6 +155,7 @@ interface krb5pac + PAC_CONSTRAINED_DELEGATION_CTR constrained_delegation; + [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; + [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; ++ [case(PAC_TYPE_ATTRIBUTES_INFO)] PAC_ATTRIBUTES_INFO attributes_info; + /* when new PAC info types are added they are supposed to be done + in such a way that they are backwards compatible with existing + servers. This makes it safe to just use a [default] for +-- +2.27.0 + diff --git a/backport-0052-CVE-2022-2031-CVE-2022-32744.patch b/backport-0052-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..0afe413e3ae136f57c9843b87be8e3886da7fca3 --- /dev/null +++ b/backport-0052-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,50 @@ +From f4ed37ad6aa0359f4799188d2b1d30571c6b42a6 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 26 Oct 2021 20:33:49 +1300 +Subject: [PATCH] CVE-2020-25719 krb5pac.idl: Add PAC_REQUESTER_SID PAC buffer + type + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14561 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +--- + librpc/idl/krb5pac.idl | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/librpc/idl/krb5pac.idl b/librpc/idl/krb5pac.idl +index 01af1d0..84f72f7 100644 +--- a/librpc/idl/krb5pac.idl ++++ b/librpc/idl/krb5pac.idl +@@ -121,6 +121,10 @@ interface krb5pac + PAC_ATTRIBUTE_INFO_FLAGS flags; + } PAC_ATTRIBUTES_INFO; + ++ typedef struct { ++ dom_sid sid; ++ } PAC_REQUESTER_SID; ++ + typedef [public] struct { + PAC_LOGON_INFO *info; + } PAC_LOGON_INFO_CTR; +@@ -138,7 +142,8 @@ interface krb5pac + PAC_TYPE_CONSTRAINED_DELEGATION = 11, + PAC_TYPE_UPN_DNS_INFO = 12, + PAC_TYPE_TICKET_CHECKSUM = 16, +- PAC_TYPE_ATTRIBUTES_INFO = 17 ++ PAC_TYPE_ATTRIBUTES_INFO = 17, ++ PAC_TYPE_REQUESTER_SID = 18 + } PAC_TYPE; + + typedef struct { +@@ -156,6 +161,7 @@ interface krb5pac + [case(PAC_TYPE_UPN_DNS_INFO)] PAC_UPN_DNS_INFO upn_dns_info; + [case(PAC_TYPE_TICKET_CHECKSUM)] PAC_SIGNATURE_DATA ticket_checksum; + [case(PAC_TYPE_ATTRIBUTES_INFO)] PAC_ATTRIBUTES_INFO attributes_info; ++ [case(PAC_TYPE_REQUESTER_SID)] PAC_REQUESTER_SID requester_sid; + /* when new PAC info types are added they are supposed to be done + in such a way that they are backwards compatible with existing + servers. This makes it safe to just use a [default] for +-- +2.27.0 + diff --git a/backport-0053-CVE-2022-2031-CVE-2022-32744.patch b/backport-0053-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..d271ee3b76f5d143ca4879f9224f23f452c0e0ef --- /dev/null +++ b/backport-0053-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,63 @@ +From 19719003af110c6ed664970cddb353d60805ba91 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Thu, 30 Sep 2021 14:55:06 +1300 +Subject: [PATCH] CVE-2020-25718 kdc: Remove unused samba_kdc_get_pac_blob() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14558 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Joseph Sutton +--- + source4/kdc/pac-glue.c | 21 --------------------- + source4/kdc/pac-glue.h | 3 --- + 2 files changed, 24 deletions(-) + +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index 2aa3d6c..32a9228 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -956,27 +956,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + return NT_STATUS_OK; + } + +-NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, +- struct samba_kdc_entry *p, +- DATA_BLOB **_logon_info_blob) +-{ +- NTSTATUS nt_status; +- DATA_BLOB *upn_blob = NULL; +- +- nt_status = samba_kdc_get_pac_blobs(mem_ctx, p, +- _logon_info_blob, +- NULL, /* cred_blob */ +- &upn_blob, +- NULL, +- NULL); +- if (!NT_STATUS_IS_OK(nt_status)) { +- return nt_status; +- } +- +- TALLOC_FREE(upn_blob); +- return NT_STATUS_OK; +-} +- + NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + krb5_context context, + struct ldb_context *samdb, +diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h +index 9288924..3f4f470 100644 +--- a/source4/kdc/pac-glue.h ++++ b/source4/kdc/pac-glue.h +@@ -56,9 +56,6 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx, + const krb5_boolean *pac_request, + DATA_BLOB **_requester_sid_blob, + struct auth_user_info_dc **_user_info_dc); +-NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, +- struct samba_kdc_entry *skdc_entry, +- DATA_BLOB **_logon_info_blob); + + NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, + krb5_context context, +-- +2.27.0 + diff --git a/backport-0054-CVE-2022-2031-CVE-2022-32744.patch b/backport-0054-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..2fa06d4f162c1289b362a9b43af583f78ca977e3 --- /dev/null +++ b/backport-0054-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,251 @@ +From d68a530c66cf1200db112607d6c6bd91ad828232 Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 8 Oct 2021 08:29:51 +1300 +Subject: [PATCH] CVE-2020-25719 kdc: Avoid races and multiple DB lookups in + s4u2self check + +Looking up the DB twice is subject to a race and is a poor +use of resources, so instead just pass in the record we +already got when trying to confirm that the server in +S4U2Self is the same as the requesting client. + +The client record has already been bound to the the +original client by the SID check in the PAC. + +Likewise by looking up server only once we ensure +that the keys looked up originally are in the record +we confirm the SID for here. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14686 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Joseph Sutton +--- + source4/heimdal/kdc/krb5tgs.c | 26 +++++++++++------ + source4/heimdal/lib/hdb/hdb.h | 2 +- + source4/kdc/db-glue.c | 54 ++++++++++++----------------------- + source4/kdc/db-glue.h | 5 ++-- + source4/kdc/hdb-samba4.c | 43 ++++++++-------------------- + 5 files changed, 52 insertions(+), 78 deletions(-) + +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index 301ca92091a..d4a1c78e153 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -313,7 +313,7 @@ check_constrained_delegation(krb5_context context, + * Determine if s4u2self is allowed from this client to this server + * + * For example, regardless of the principal being impersonated, if the +- * 'client' and 'server' are the same, then it's safe. ++ * 'client' and 'server' (target) are the same, then it's safe. + */ + + static krb5_error_code +@@ -321,18 +321,28 @@ check_s4u2self(krb5_context context, + krb5_kdc_configuration *config, + HDB *clientdb, + hdb_entry_ex *client, +- krb5_const_principal server) ++ hdb_entry_ex *target_server, ++ krb5_const_principal target_server_principal) + { + krb5_error_code ret; + +- /* if client does a s4u2self to itself, that ok */ +- if (krb5_principal_compare(context, client->entry.principal, server) == TRUE) +- return 0; +- ++ /* ++ * Always allow the plugin to check, this might be faster, allow a ++ * policy or audit check and can look into the DB records ++ * directly ++ */ + if (clientdb->hdb_check_s4u2self) { +- ret = clientdb->hdb_check_s4u2self(context, clientdb, client, server); ++ ret = clientdb->hdb_check_s4u2self(context, ++ clientdb, ++ client, ++ target_server); + if (ret == 0) + return 0; ++ } else if (krb5_principal_compare(context, ++ client->entry.principal, ++ target_server_principal) == TRUE) { ++ /* if client does a s4u2self to itself, and there is no plugin, that is ok */ ++ return 0; + } else { + ret = KRB5KDC_ERR_BADOPTION; + } +@@ -1774,7 +1784,7 @@ server_lookup: + * Check that service doing the impersonating is + * requesting a ticket to it-self. + */ +- ret = check_s4u2self(context, config, clientdb, client, sp); ++ ret = check_s4u2self(context, config, clientdb, client, server, sp); + if (ret) { + kdc_log(context, config, 0, "S4U2Self: %s is not allowed " + "to impersonate to service " +diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h +index 6a09ecb6fe1..5ef9d9565f3 100644 +--- a/source4/heimdal/lib/hdb/hdb.h ++++ b/source4/heimdal/lib/hdb/hdb.h +@@ -266,7 +266,7 @@ typedef struct HDB{ + /** + * Check if s4u2self is allowed from this client to this server + */ +- krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal); ++ krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, hdb_entry_ex *); + }HDB; + + #define HDB_INTERFACE_VERSION 7 +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index a560a1cd84b..8fe4f1ea3e9 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -2510,53 +2510,37 @@ krb5_error_code samba_kdc_nextkey(krb5_context context, + + /* Check if a given entry may delegate or do s4u2self to this target principal + * +- * This is currently a very nasty hack - allowing only delegation to itself. ++ * The safest way to determine 'self' is to check the DB record made at ++ * the time the principal was presented to the KDC. + */ + krb5_error_code + samba_kdc_check_s4u2self(krb5_context context, +- struct samba_kdc_db_context *kdc_db_ctx, +- struct samba_kdc_entry *skdc_entry, +- krb5_const_principal target_principal) ++ struct samba_kdc_entry *skdc_entry_client, ++ struct samba_kdc_entry *skdc_entry_server_target) + { +- krb5_error_code ret; +- struct ldb_dn *realm_dn; +- struct ldb_message *msg; + struct dom_sid *orig_sid; + struct dom_sid *target_sid; +- const char *delegation_check_attrs[] = { +- "objectSid", NULL +- }; +- +- TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_s4u2self"); +- +- if (!mem_ctx) { +- ret = ENOMEM; +- krb5_set_error_message(context, ret, "samba_kdc_check_s4u2self: talloc_named() failed!"); +- return ret; +- } +- +- ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal, +- SDB_F_GET_CLIENT|SDB_F_GET_SERVER, +- delegation_check_attrs, &realm_dn, &msg); +- +- if (ret != 0) { +- talloc_free(mem_ctx); +- return ret; +- } ++ TALLOC_CTX *frame = talloc_stackframe(); + +- orig_sid = samdb_result_dom_sid(mem_ctx, skdc_entry->msg, "objectSid"); +- target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); ++ orig_sid = samdb_result_dom_sid(frame, ++ skdc_entry_client->msg, ++ "objectSid"); ++ target_sid = samdb_result_dom_sid(frame, ++ skdc_entry_server_target->msg, ++ "objectSid"); + +- /* Allow delegation to the same principal, even if by a different +- * name. The easy and safe way to prove this is by SID +- * comparison */ ++ /* ++ * Allow delegation to the same record (representing a ++ * principal), even if by a different name. The easy and safe ++ * way to prove this is by SID comparison ++ */ + if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { +- talloc_free(mem_ctx); ++ talloc_free(frame); + return KRB5KDC_ERR_BADOPTION; + } + +- talloc_free(mem_ctx); +- return ret; ++ talloc_free(frame); ++ return 0; + } + + /* Certificates printed by a the Certificate Authority might have a +diff --git a/source4/kdc/db-glue.h b/source4/kdc/db-glue.h +index aa630f5d349..cadfac1deb8 100644 +--- a/source4/kdc/db-glue.h ++++ b/source4/kdc/db-glue.h +@@ -40,9 +40,8 @@ krb5_error_code samba_kdc_nextkey(krb5_context context, + + krb5_error_code + samba_kdc_check_s4u2self(krb5_context context, +- struct samba_kdc_db_context *kdc_db_ctx, +- struct samba_kdc_entry *skdc_entry, +- krb5_const_principal target_principal); ++ struct samba_kdc_entry *skdc_entry_client, ++ struct samba_kdc_entry *skdc_entry_server_target); + + krb5_error_code + samba_kdc_check_pkinit_ms_upn_match(krb5_context context, +diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c +index 38ce9807c02..f0939193ad7 100644 +--- a/source4/kdc/hdb-samba4.c ++++ b/source4/kdc/hdb-samba4.c +@@ -274,38 +274,19 @@ hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db, + + static krb5_error_code + hdb_samba4_check_s4u2self(krb5_context context, HDB *db, +- hdb_entry_ex *entry, +- krb5_const_principal target_principal) ++ hdb_entry_ex *client_entry, ++ hdb_entry_ex *server_target_entry) + { +- struct samba_kdc_db_context *kdc_db_ctx; +- struct samba_kdc_entry *skdc_entry; +- krb5_error_code ret; +- +- kdc_db_ctx = talloc_get_type_abort(db->hdb_db, +- struct samba_kdc_db_context); +- skdc_entry = talloc_get_type_abort(entry->ctx, +- struct samba_kdc_entry); +- +- ret = samba_kdc_check_s4u2self(context, kdc_db_ctx, +- skdc_entry, +- target_principal); +- switch (ret) { +- case 0: +- break; +- case SDB_ERR_WRONG_REALM: +- ret = HDB_ERR_WRONG_REALM; +- break; +- case SDB_ERR_NOENTRY: +- ret = HDB_ERR_NOENTRY; +- break; +- case SDB_ERR_NOT_FOUND_HERE: +- ret = HDB_ERR_NOT_FOUND_HERE; +- break; +- default: +- break; +- } +- +- return ret; ++ struct samba_kdc_entry *skdc_client_entry ++ = talloc_get_type_abort(client_entry->ctx, ++ struct samba_kdc_entry); ++ struct samba_kdc_entry *skdc_server_target_entry ++ = talloc_get_type_abort(server_target_entry->ctx, ++ struct samba_kdc_entry); ++ ++ return samba_kdc_check_s4u2self(context, ++ skdc_client_entry, ++ skdc_server_target_entry); + } + + static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx, +-- +2.33.0 + diff --git a/backport-0055-CVE-2022-2031-CVE-2022-32744.patch b/backport-0055-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000000000000000000000000000000000000..bd96c52d1daac1ae6ab2daec20df86ee0758b896 --- /dev/null +++ b/backport-0055-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,28 @@ +From b6a25f5f016aef39c3b1d7be8b3ecfe021c03c83 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:00:07 +1300 +Subject: [PATCH] kdc: Match Windows error code for mismatching sname + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +Conflict: remove selftest/knownfail_heimdal_kdc +--- + source4/kdc/db-glue.c | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index bfde2baf0b5..4c56e6cbadd 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -2564,7 +2564,7 @@ samba_kdc_check_s4u2self(krb5_context context, + */ + if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { + talloc_free(frame); +- return KRB5KDC_ERR_BADOPTION; ++ return KRB5KRB_AP_ERR_BADMATCH; + } + + talloc_free(frame); +-- +2.33.0 + diff --git a/backport-CVE-2022-32742.patch b/backport-CVE-2022-32742.patch new file mode 100644 index 0000000000000000000000000000000000000000..391824514a2f6c20ec63322a9a07689a95252f95 --- /dev/null +++ b/backport-CVE-2022-32742.patch @@ -0,0 +1,217 @@ +From f6e1750c4fc966c29c2e0663d3c04e87057fa0c3 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Tue, 7 Jun 2022 09:40:45 -0700 +Subject: [PATCH 98/99] CVE-2022-32742: s4: torture: Add raw.write.bad-write + test. + +Reproduces the test code in: + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Add knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 + + source4/torture/raw/write.c | 89 ++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + create mode 100644 selftest/knownfail.d/bad-write + +diff --git a/selftest/knownfail.d/bad-write b/selftest/knownfail.d/bad-write +new file mode 100644 +index 00000000000..5fc16606a13 +--- /dev/null ++++ b/selftest/knownfail.d/bad-write +@@ -0,0 +1,2 @@ ++^samba3.raw.write.bad-write\(nt4_dc_smb1\) ++^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git a/source4/torture/raw/write.c b/source4/torture/raw/write.c +index 0a2f50f425b..661485bb548 100644 +--- a/source4/torture/raw/write.c ++++ b/source4/torture/raw/write.c +@@ -25,6 +25,7 @@ + #include "libcli/libcli.h" + #include "torture/util.h" + #include "torture/raw/proto.h" ++#include "libcli/raw/raw_proto.h" + + #define CHECK_STATUS(status, correct) do { \ + if (!NT_STATUS_EQUAL(status, correct)) { \ +@@ -694,6 +695,93 @@ done: + return ret; + } + ++/* ++ test a deliberately bad SMB1 write. ++*/ ++static bool test_bad_write(struct torture_context *tctx, ++ struct smbcli_state *cli) ++{ ++ bool ret = false; ++ int fnum = -1; ++ struct smbcli_request *req = NULL; ++ const char *fname = BASEDIR "\\badwrite.txt"; ++ bool ok = false; ++ ++ if (!torture_setup_dir(cli, BASEDIR)) { ++ torture_fail(tctx, "failed to setup basedir"); ++ } ++ ++ torture_comment(tctx, "Testing RAW_BAD_WRITE\n"); ++ ++ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); ++ if (fnum == -1) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Failed to create %s - %s\n", ++ fname, ++ smbcli_errstr(cli->tree))); ++ } ++ ++ req = smbcli_request_setup(cli->tree, ++ SMBwrite, ++ 5, ++ 0); ++ if (req == NULL) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "talloc fail\n")); ++ } ++ ++ SSVAL(req->out.vwv, VWV(0), fnum); ++ SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */ ++ SIVAL(req->out.vwv, VWV(2), 0); /* offset */ ++ SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */ ++ ++ if (!smbcli_request_send(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Send failed\n")); ++ } ++ ++ if (!smbcli_request_receive(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Reveive failed\n")); ++ } ++ ++ /* ++ * Check for expected error codes. ++ * ntvfs returns NT_STATUS_UNSUCCESSFUL. ++ */ ++ ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) || ++ NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL)); ++ ++ if (!ok) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Should have returned " ++ "NT_STATUS_INVALID_PARAMETER or " ++ "NT_STATUS_UNSUCCESSFUL " ++ "got %s\n", ++ nt_errstr(req->status))); ++ } ++ ++ ret = true; ++ ++done: ++ if (req != NULL) { ++ smbcli_request_destroy(req); ++ } ++ if (fnum != -1) { ++ smbcli_close(cli->tree, fnum); ++ } ++ smb_raw_exit(cli->session); ++ smbcli_deltree(cli->tree, BASEDIR); ++ return ret; ++} ++ + /* + basic testing of write calls + */ +@@ -705,6 +793,7 @@ struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx) + torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock); + torture_suite_add_1smb_test(suite, "write close", test_writeclose); + torture_suite_add_1smb_test(suite, "writex", test_writex); ++ torture_suite_add_1smb_test(suite, "bad-write", test_bad_write); + + return suite; + } +-- +2.25.1 + + +From 7720e0acfd7ea6a2339f3e389aa8dcedd6174095 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 8 Jun 2022 13:50:51 -0700 +Subject: [PATCH 99/99] CVE-2022-32742: s3: smbd: Harden the smbreq_bufrem() + macro. + +Fixes the raw.write.bad-write test. + +NB. We need the two (==0) changes in source3/smbd/reply.c +as the gcc optimizer now knows that the return from +smbreq_bufrem() can never be less than zero. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Remove knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 -- + source3/include/smb_macros.h | 2 +- + source3/smbd/reply.c | 4 ++-- + 3 files changed, 3 insertions(+), 5 deletions(-) + delete mode 100644 selftest/knownfail.d/bad-write + +diff --git a/selftest/knownfail.d/bad-write b/selftest/knownfail.d/bad-write +deleted file mode 100644 +index 5fc16606a13..00000000000 +--- a/selftest/knownfail.d/bad-write ++++ /dev/null +@@ -1,2 +0,0 @@ +-^samba3.raw.write.bad-write\(nt4_dc_smb1\) +-^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h +index def122727f0..de1322a503b 100644 +--- a/source3/include/smb_macros.h ++++ b/source3/include/smb_macros.h +@@ -152,7 +152,7 @@ + + /* the remaining number of bytes in smb buffer 'buf' from pointer 'p'. */ + #define smb_bufrem(buf, p) (smb_buflen(buf)-PTR_DIFF(p, smb_buf(buf))) +-#define smbreq_bufrem(req, p) (req->buflen - PTR_DIFF(p, req->buf)) ++#define smbreq_bufrem(req, p) ((req)->buflen < PTR_DIFF((p), (req)->buf) ? 0 : (req)->buflen - PTR_DIFF((p), (req)->buf)) + + + /* Note that chain_size must be available as an extern int to this macro. */ +diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c +index f33326564f7..b5abe588910 100644 +--- a/source3/smbd/reply.c ++++ b/source3/smbd/reply.c +@@ -342,7 +342,7 @@ size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + *err = NT_STATUS_INVALID_PARAMETER; + return 0; + } +@@ -380,7 +380,7 @@ size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + return 0; + } + +-- +2.25.1 + diff --git a/samba.spec b/samba.spec index 1f6bb4d3cbe7eee498b02db96dbc62367c1cbb54..21c71f1f269c9ec9097311ec541f06a6330d1a2e 100644 --- a/samba.spec +++ b/samba.spec @@ -49,7 +49,7 @@ Name: samba Version: 4.11.12 -Release: 12 +Release: 13 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -191,6 +191,77 @@ Patch6262: backport-005-CVE-2021-3670.patch Patch6263: backport-006-CVE-2021-3670.patch Patch6264: backport-007-CVE-2021-3670.patch +Patch6265: backport-0001-CVE-2022-32746.patch +Patch6266: backport-0002-CVE-2022-32746.patch +Patch6267: backport-0003-CVE-2022-32746.patch +Patch6268: backport-0004-CVE-2022-32746.patch +Patch6269: backport-0005-CVE-2022-32746.patch +Patch6270: backport-0006-CVE-2022-32746.patch +Patch6271: backport-0007-CVE-2022-32746.patch +Patch6272: backport-0008-CVE-2022-32746.patch +Patch6273: backport-0009-CVE-2022-32746.patch +Patch6274: backport-0010-CVE-2022-32746.patch +Patch6275: backport-0011-CVE-2022-32746.patch +Patch6276: backport-0012-CVE-2022-32746.patch +Patch6277: backport-0013-CVE-2022-32746.patch +Patch6278: backport-0001-CVE-2022-2031-CVE-2022-32744.patch +Patch6279: backport-0002-CVE-2022-2031-CVE-2022-32744.patch +Patch6280: backport-0003-CVE-2022-2031-CVE-2022-32744.patch +Patch6281: backport-0004-CVE-2022-2031-CVE-2022-32744.patch +Patch6282: backport-0005-CVE-2022-2031-CVE-2022-32744.patch +Patch6283: backport-0006-CVE-2022-2031-CVE-2022-32744.patch +Patch6284: backport-0007-CVE-2022-2031-CVE-2022-32744.patch +Patch6285: backport-0008-CVE-2022-2031-CVE-2022-32744.patch +Patch6286: backport-0009-CVE-2022-2031-CVE-2022-32744.patch +Patch6287: backport-0010-CVE-2022-2031-CVE-2022-32744.patch +Patch6288: backport-0011-CVE-2022-2031-CVE-2022-32744.patch +Patch6289: backport-0012-CVE-2022-2031-CVE-2022-32744.patch +Patch6290: backport-0013-CVE-2022-2031-CVE-2022-32744.patch +Patch6291: backport-0014-CVE-2022-2031-CVE-2022-32744.patch +Patch6292: backport-0015-CVE-2022-2031-CVE-2022-32744.patch +Patch6293: backport-0016-CVE-2022-2031-CVE-2022-32744.patch +Patch6294: backport-0017-CVE-2022-2031-CVE-2022-32744.patch +Patch6295: backport-0018-CVE-2022-2031-CVE-2022-32744.patch +Patch6296: backport-0019-CVE-2022-2031-CVE-2022-32744.patch +Patch6297: backport-0020-CVE-2022-2031-CVE-2022-32744.patch +Patch6298: backport-0021-CVE-2022-2031-CVE-2022-32744.patch +Patch6299: backport-0022-CVE-2022-2031-CVE-2022-32744.patch +Patch6300: backport-0023-CVE-2022-2031-CVE-2022-32744.patch +Patch6301: backport-0024-CVE-2022-2031-CVE-2022-32744.patch +Patch6302: backport-0025-CVE-2022-2031-CVE-2022-32744.patch +Patch6303: backport-0026-CVE-2022-2031-CVE-2022-32744.patch +Patch6304: backport-0027-CVE-2022-2031-CVE-2022-32744.patch +Patch6305: backport-0028-CVE-2022-2031-CVE-2022-32744.patch +Patch6306: backport-0029-CVE-2022-2031-CVE-2022-32744.patch +Patch6307: backport-0030-CVE-2022-2031-CVE-2022-32744.patch +Patch6308: backport-0031-CVE-2022-2031-CVE-2022-32744.patch +Patch6309: backport-0032-CVE-2022-2031-CVE-2022-32744.patch +Patch6310: backport-0033-CVE-2022-2031-CVE-2022-32744.patch +Patch6311: backport-0034-CVE-2022-2031-CVE-2022-32744.patch +Patch6312: backport-0035-CVE-2022-2031-CVE-2022-32744.patch +Patch6313: backport-0036-CVE-2022-2031-CVE-2022-32744.patch +Patch6314: backport-0037-CVE-2022-2031-CVE-2022-32744.patch +Patch6315: backport-0038-CVE-2022-2031-CVE-2022-32744.patch +Patch6316: backport-0039-CVE-2022-2031-CVE-2022-32744.patch +Patch6317: backport-0040-CVE-2022-2031-CVE-2022-32744.patch +Patch6318: backport-0041-CVE-2022-2031-CVE-2022-32744.patch +Patch6319: backport-0042-CVE-2022-2031-CVE-2022-32744.patch +Patch6320: backport-0043-CVE-2022-2031-CVE-2022-32744.patch +Patch6321: backport-0044-CVE-2022-2031-CVE-2022-32744.patch +Patch6322: backport-0045-CVE-2022-2031-CVE-2022-32744.patch +Patch6323: backport-0046-CVE-2022-2031-CVE-2022-32744.patch +Patch6324: backport-0047-CVE-2022-2031-CVE-2022-32744.patch +Patch6325: backport-0048-CVE-2022-2031-CVE-2022-32744.patch +Patch6326: backport-0049-CVE-2022-2031-CVE-2022-32744.patch +Patch6327: backport-0050-CVE-2022-2031-CVE-2022-32744.patch +Patch6328: backport-0051-CVE-2022-2031-CVE-2022-32744.patch +Patch6329: backport-0052-CVE-2022-2031-CVE-2022-32744.patch +Patch6330: backport-0053-CVE-2022-2031-CVE-2022-32744.patch +Patch6331: backport-0054-CVE-2022-2031-CVE-2022-32744.patch +Patch6332: backport-0055-CVE-2022-2031-CVE-2022-32744.patch +Patch6333: backport-CVE-2022-32742.patch + + BuildRequires: avahi-devel cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel BuildRequires: libcap-devel libcmocka-devel libnsl2-devel libtirpc-devel libuuid-devel libxslt lmdb ncurses-devel openldap-devel @@ -3177,6 +3248,12 @@ fi %{_mandir}/man* %changelog +* Sat Aug 06 2022 xinghe - 4.11.12-13 +- Type:cves +- CVE:CVE-2022-32746 CVE-2022-32744 CVE-2022-2031 CVE-2022-32742 +- SUG:NA +- DESC:fix CVE-2022-32746 CVE-2022-32744 CVE-2022-2031 CVE-2022-32742 + * Tue Jun 21 2022 gaihuiying - 4.11.12-12 - Type:CVE - CVE:CVE-2021-3670