fix CVE-2022-32746 CVE-2022-32744 CVE-2022-2031 CVE-2022-32742

This commit is contained in:
xinghe 2022-08-09 18:26:35 +08:00
parent 812503e64d
commit 6b0bced228
70 changed files with 8530 additions and 1 deletions

View File

@ -0,0 +1,73 @@
From 258710a9f2145939d959a8512e0d40dfd32ef1b7 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
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 <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,35 @@
From c2bbe774ce03661666a1f48922a9ab681ef4f64b Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
---
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;i<msg2->num_elements;i++) {
struct ldb_message_element *el = &msg2->elements[i];
--
2.25.1

View File

@ -0,0 +1,104 @@
From 8048b6fe8cfd2887090a5aec682060b396794f6b Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,359 @@
From eadd3b8844d1e4162558f443e5cd4905f12667e6 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,38 @@
From a68553792a8512a2d266bbb86f064f78b5482a65 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,103 @@
From 2149108966f4159a218a901c19bea3921d68fa1e Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(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

View File

@ -0,0 +1,37 @@
From 582ac171364f0c28f54eaf4f21b5bfa7569b5233 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,604 @@
From 30fb296a38a72fd91161c4f48be3a0472479f2ff Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
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

View File

@ -0,0 +1,39 @@
From 0526d27e9eddd9c2a54434cf0dcdb136a6c659e4 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,168 @@
From 60a136bcc6c993f9462247332624be17bc6dd9bb Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
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, "<SID=%s>",
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

View File

@ -0,0 +1,30 @@
From 2869b5aa3148869edf0d079266542aef6e64608e Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,94 @@
From 36a1c87654cf011a597901d43a16dfbc0fecf330 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,53 @@
From 535b5a366a2ad054f729e57e282e402cf13b2efc Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,64 @@
From 5cdec75f8bceee0e4996682d09104ff076e241b3 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
[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

View File

@ -0,0 +1,39 @@
From bedd0b768c3f92645af033399aefd7ee971d9150 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,57 @@
From 048c400e02c5fef623ed95dfdd92bc1591ef6710 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,30 @@
From 49dd9042f4ee380fa1dafcebcb54d0e1f0852463 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,69 @@
From 1fcd10069f774758c8234818ebe81b7ee5966d1d Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,114 @@
From faa61ab3053d077ac9d0aa67e955217e85b660f4 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,67 @@
From d15ace2d81783a92474e2dbe6c02f20589aa70f0 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
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

View File

@ -0,0 +1,180 @@
From 4e5fb78c3dcff60aa8fd4b07dad4660bbb30532b Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,101 @@
From d3bd072c0e9b3810921048663ac59a8f70739b31 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
.../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

View File

@ -0,0 +1,276 @@
From 512a2617b1593bdc16caeeeda4312a581cbb34e9 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,475 @@
From b8a81c06357f0360dbb3b59b1da1108bd1574810 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
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; i<el->num_values; i++) {
+ (*sids)[0] = *primary_sid;
+
+ for (i = 0; i<el->num_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

View File

@ -0,0 +1,895 @@
From f419753d1c7a373fb32ffe20930a6e084e44b44d Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,496 @@
From 45ff2b32361fb87a4f4bbc61f2620e2006666f34 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
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

View File

@ -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 <asn@samba.org>
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
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

View File

@ -0,0 +1,28 @@
From 06a0a75b16bace9c29568653d9e4bde4050c5ee5 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(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

View File

@ -0,0 +1,27 @@
From 33d5e5ad3a06ca6a1a62e64d323580ca60f068b8 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Thu, 18 Nov 2021 16:22:34 +1300
Subject: [PATCH 36/99] s4:torture: Fix typo
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,32 @@
From 5556f97c782c9be9af47c76f2432bb8480bc0622 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,30 @@
From 93a5264dd68da57e172af50020f670631eeef263 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,73 @@
From 72afa2641c24bd18a32463f0b0de7e91feb54290 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,34 @@
From 29f15fe2d92831dcf5f4eb6d295df866ff689ee3 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(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

View File

@ -0,0 +1,37 @@
From 49aafce0a705d47ffd4753ce6c6f452c4f7aa882 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
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

View File

@ -0,0 +1,55 @@
From 3fc519edec0159535baa0b659861b73f40632110 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Tue, 7 Dec 2021 13:15:38 +1300
Subject: [PATCH 51/99] kdc: Canonicalize realm for enterprise principals
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
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

View File

@ -0,0 +1,269 @@
From c0395578c50fbc4f1946e2f5a065d94f67212eb0 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
[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

View File

@ -0,0 +1,34 @@
From 6843c44a45044808f90687f85183e7111a465d1f Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,53 @@
From 1b38a28bcaebdae0128518605a422a194747a60f Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,165 @@
From f6c5a60336de8fd67a2ef371dd2ee4cf75c53904 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,57 @@
From 29ec8b2369b5f5e2a660a3165d2528982514a0f2 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,41 @@
From 3a8da51396f3bf9d4caf8dbd4e75a0314aa47046 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,36 @@
From cf9e37604409ba0c3c5904af40beb2975c309ad4 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
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

View File

@ -0,0 +1,38 @@
From cf749fac346ef59c91a9ea87f5e7ddec2e5649c7 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
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

View File

@ -0,0 +1,245 @@
From 198256e2184897300e1cea4343437c3b7b6f74ad Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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 <abartlet@samba.org> 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <abartlet@samba.org> 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 <http://www.gnu.org/licenses/>.
+*/
+
+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 <abartlet@samba.org> 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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

View File

@ -0,0 +1,80 @@
From 69e742e6208bd471eb509795bd753a0c98392bf6 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,41 @@
From b5adf7cc6d740c8f4f7b5888f106de24a1181da7 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
[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

View File

@ -0,0 +1,85 @@
From 91a1b0955a053f73e6d531f0f12eaa604aca79d7 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
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 <<EOF
-Usage: test_passwords.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX SMBCLIENT
+Usage: test_kpasswd_heimdal.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX SMBCLIENT
EOF
exit 1;
fi
@@ -27,6 +27,8 @@ smbclient="$samba_bindir/smbclient"
samba_kinit=$samba_bindir/samba4kinit
samba_kpasswd=$samba_bindir/samba4kpasswd
+mit_kpasswd="$(command -v kpasswd)"
+
samba_tool="$samba_bindir/samba-tool"
net_tool="$samba_bindir/net"
texpect="$samba_bindir/texpect"
@@ -142,6 +144,37 @@ testit "kpasswd change user password" \
TEST_PASSWORD=$TEST_PASSWORD_NEW
TEST_PASSWORD_NEW="testPaSS@03%"
+###########################################################
+### CVE-2022-XXXXX
+###########################################################
+
+if [ -n "${mit_kpasswd}" ]; then
+ cat > "${PREFIX}/tmpkpasswdscript" <<EOF
+expect Password for ${TEST_PRINCIPAL}
+password ${TEST_PASSWORD}\n
+expect Enter new password
+send ${TEST_PASSWORD_NEW}\n
+expect Enter it again
+send ${TEST_PASSWORD_NEW}\n
+expect Password changed.
+EOF
+
+ SAVE_KRB5_CONFIG="${KRB5_CONFIG}"
+ KRB5_CONFIG="${PREFIX}/tmpkrb5.conf"
+ export KRB5_CONFIG
+ sed -e 's/\[libdefaults\]/[libdefaults]\n canonicalize = yes/' \
+ "${SAVE_KRB5_CONFIG}" > "${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

View File

@ -0,0 +1,52 @@
From 36d94ffb9c99f3e515024424020e3e03e98f34f5 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@samba.org>
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 <asn@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
[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

View File

@ -0,0 +1,239 @@
From f68877af829bf73da8e965c9458a9846d1757038 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,162 @@
From fa4742e1b9dea0b9c379f00666478bd41c021634 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,150 @@
From 3cab62893668742781551dae6505558e47cf08b5 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <asn@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,70 @@
From 531e7b596d35785bee61f3b4289e38ece1530f94 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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 <profile.h>
#include <kdb.h>
+#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

View File

@ -0,0 +1,78 @@
From d40593be83144713cfc43e4eb1c7bc2d925a0da0 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
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

View File

@ -0,0 +1,79 @@
From 42ba919c06c24c42ef123304de0c2ca8c689591a Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,76 @@
From 997f50c66471071efb8e02d8efbe4bf5d932e7ee Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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&<address>' 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 <address> is the string form of a pointer to a talloced struct hdb_samba_context
*/
--
2.25.1

View File

@ -0,0 +1,146 @@
From c0c4b7a4bd229bd36d586faec6249baaba8e7adc Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,86 @@
From 340181bc1100fa31c63af88214a3d8328b944fe9 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,171 @@
From 4b61092459b403b2945daa9082052366f3508b69 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,83 @@
From 89c6e36938c27b572573b06d1b35db210bfda99b Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
---
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

View File

@ -0,0 +1,136 @@
From d5af460403d3949ba266f5c74f051247cd7ce752 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
[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

View File

@ -0,0 +1,43 @@
From a6231af1f1c03cd81614332f867916e1748e03a8 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
[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

View File

@ -0,0 +1,39 @@
From 6acbb94daddb94a795e0b506bb7637ed15578cc5 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Wed, 1 Sep 2021 15:39:19 +1200
Subject: [PATCH] krb5pac.idl: Add ticket checksum PAC buffer type
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Isaac Boukris <iboukris@samba.org>
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

View File

@ -0,0 +1,56 @@
From c22162544b70c5e546d973506cdb3ca197bdb375 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,50 @@
From f4ed37ad6aa0359f4799188d2b1d30571c6b42a6 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
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

View File

@ -0,0 +1,63 @@
From 19719003af110c6ed664970cddb353d60805ba91 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,251 @@
From d68a530c66cf1200db112607d6c6bd91ad828232 Mon Sep 17 00:00:00 2001
From: Andrew Bartlett <abartlet@samba.org>
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 <abartlet@samba.org>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
---
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

View File

@ -0,0 +1,28 @@
From b6a25f5f016aef39c3b1d7be8b3ecfe021c03c83 Mon Sep 17 00:00:00 2001
From: Joseph Sutton <josephsutton@catalyst.net.nz>
Date: Tue, 23 Nov 2021 20:00:07 +1300
Subject: [PATCH] kdc: Match Windows error code for mismatching sname
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
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

View File

@ -0,0 +1,217 @@
From f6e1750c4fc966c29c2e0663d3c04e87057fa0c3 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
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 <jra@samba.org>
Reviewed-by: David Disseldorp <ddiss@samba.org>
---
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 <jra@samba.org>
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 <jra@samba.org>
Reviewed-by: David Disseldorp <ddiss@samba.org>
---
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

View File

@ -49,7 +49,7 @@
Name: samba
Version: 4.11.12
Release: 11
Release: 12
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
* Tue Aug 09 2022 xinghe <xinghe@h-partners.com> - 4.11.12-12
- 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 <eaglegai@163.com> - 4.11.12-11
- Type:CVE
- CVE:CVE-2021-3670