mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-08-28 01:55:13 +00:00
samba: Fix CVE-2026-4408
This patch applies the upstream Samba security backport for CVE-2026-4408. The upstream security bundle is referenced in [1], and the public CVE advisory is referenced in [2]. The individual backported commit links are recorded in the embedded patch headers. Only the CVE-2026-4408-relevant commits from [1] are backported: [PATCH 11/31] through [PATCH 21/31] and [PATCH 25/31] through [PATCH 31/31]. The remaining bundle commits are intentionally omitted because they fix separate CVEs: CVE-2026-1933, CVE-2026-2340, CVE-2026-3012, CVE-2026-3238, and CVE-2026-4480-only changes. [1] https://www.samba.org/samba/ftp/patches/security/samba-4.22.9-security-2026-05-25.patch [2] https://www.samba.org/samba/security/CVE-2026-4408.html Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
committed by
Anuj Mittal
parent
860fb40522
commit
3f554a5dee
@@ -0,0 +1,75 @@
|
||||
From 26b64ec55944b375ead223a214c5f4301329511f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:20:15 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: inline
|
||||
string_sub2() into string_sub() the only caller
|
||||
|
||||
This will simplify further changes.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/26b64ec55944b375ead223a214c5f4301329511f]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 26b64ec55944b375ead223a214c5f4301329511f)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 20 ++------------------
|
||||
1 file changed, 2 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index b7b5588da863..26362ca77b2c 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -47,10 +47,9 @@
|
||||
use of len==0 which was for no length checks to be done.
|
||||
**/
|
||||
|
||||
-static void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
|
||||
- bool remove_unsafe_characters, bool replace_once,
|
||||
- bool allow_trailing_dollar)
|
||||
+void string_sub(char *s, const char *pattern, const char *insert, size_t len)
|
||||
{
|
||||
+ bool remove_unsafe_characters = true;
|
||||
char *p;
|
||||
size_t ls, lp, li, i;
|
||||
|
||||
@@ -79,13 +78,6 @@ static void string_sub2(char *s,const char *pattern, const char *insert, size_t
|
||||
for (i=0;i<li;i++) {
|
||||
switch (insert[i]) {
|
||||
case '$':
|
||||
- /* allow a trailing $
|
||||
- * (as in machine accounts) */
|
||||
- if (allow_trailing_dollar && (i == li - 1 )) {
|
||||
- p[i] = insert[i];
|
||||
- break;
|
||||
- }
|
||||
- FALL_THROUGH;
|
||||
case '`':
|
||||
case '"':
|
||||
case '\'':
|
||||
@@ -107,17 +99,9 @@ static void string_sub2(char *s,const char *pattern, const char *insert, size_t
|
||||
}
|
||||
s = p + li;
|
||||
ls = ls + li - lp;
|
||||
-
|
||||
- if (replace_once)
|
||||
- break;
|
||||
}
|
||||
}
|
||||
|
||||
-void string_sub(char *s,const char *pattern, const char *insert, size_t len)
|
||||
-{
|
||||
- string_sub2( s, pattern, insert, len, true, false, false );
|
||||
-}
|
||||
-
|
||||
/**
|
||||
Similar to string_sub() but allows for any character to be substituted.
|
||||
Use with caution!
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
From d291377ac1ea515ac064ac00d59e1787db5671d1 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 7 May 2026 18:10:50 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: add
|
||||
talloc_string_sub_{mixed_quoting,unsafe}() helpers
|
||||
|
||||
This is the basic helper function for the security problems.
|
||||
|
||||
talloc_string_sub_mixed_quoting() checks for strange quoting
|
||||
in smb.conf options.
|
||||
|
||||
And talloc_string_sub_unsafe() tries to autodetect how the unsafe
|
||||
(client controlled value) and masked and single quote it,
|
||||
as a fallback for strange quoting a fixed fallback string
|
||||
is used and the caller should warn the admin and give
|
||||
hints how to fix the configuration.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
Pair-Programmed-With: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/d291377ac1ea515ac064ac00d59e1787db5671d1]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit d291377ac1ea515ac064ac00d59e1787db5671d1)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 260 ++++++++++++++++++++++++++++++++++++++++++
|
||||
lib/util/substitute.h | 17 +++
|
||||
2 files changed, 277 insertions(+)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index 30989927da72..406d8424be1a 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "system/locale.h"
|
||||
#include "debug.h"
|
||||
#ifndef SAMBA_UTIL_CORE_ONLY
|
||||
+#include "lib/util/fault.h"
|
||||
+#include "lib/util/talloc_stack.h"
|
||||
#include "charset/charset.h"
|
||||
#else
|
||||
#include "charset_compat.h"
|
||||
@@ -297,3 +299,261 @@ char *talloc_all_string_sub(TALLOC_CTX *ctx,
|
||||
return talloc_string_sub2(ctx, src, pattern, insert,
|
||||
false, false, false);
|
||||
}
|
||||
+
|
||||
+#ifndef SAMBA_UTIL_CORE_ONLY
|
||||
+
|
||||
+bool talloc_string_sub_mixed_quoting(const char *full_cmd, char variable_char)
|
||||
+{
|
||||
+ /*
|
||||
+ * Try to make sure talloc_string_sub_unsafe()
|
||||
+ * won't return NULL, instead talloc_stackframe_pool()
|
||||
+ * would panic
|
||||
+ */
|
||||
+ size_t cmd_len = full_cmd != NULL ? strlen(full_cmd) : 0;
|
||||
+ size_t pool_size = 512 + cmd_len;
|
||||
+ TALLOC_CTX *frame = talloc_stackframe_pool(pool_size);
|
||||
+ char *cmd = NULL;
|
||||
+ bool modified = false;
|
||||
+ bool masked = false;
|
||||
+ bool mixed_fallback = false;
|
||||
+
|
||||
+ cmd = talloc_string_sub_unsafe(frame,
|
||||
+ full_cmd,
|
||||
+ variable_char,
|
||||
+ "U", /* unsafe_value */
|
||||
+ "'\"%", /* unsafe_characters */
|
||||
+ '_', /* safe_character */
|
||||
+ "F", /* fallback_value */
|
||||
+ &modified,
|
||||
+ &masked,
|
||||
+ &mixed_fallback);
|
||||
+ if (cmd == NULL) {
|
||||
+ mixed_fallback = false;
|
||||
+ }
|
||||
+ TALLOC_FREE(frame);
|
||||
+ return mixed_fallback;
|
||||
+}
|
||||
+
|
||||
+char *talloc_string_sub_unsafe(TALLOC_CTX *mem_ctx,
|
||||
+ const char *orig_cmd,
|
||||
+ char variable_char,
|
||||
+ const char *unsafe_value,
|
||||
+ const char *unsafe_characters,
|
||||
+ char safe_character,
|
||||
+ const char *fallback_value,
|
||||
+ bool *_modified,
|
||||
+ bool *_masked,
|
||||
+ bool *_mixed_fallback)
|
||||
+{
|
||||
+ TALLOC_CTX *frame = talloc_stackframe();
|
||||
+ const char variable[3] =
|
||||
+ { '%', variable_char, '\0' };
|
||||
+ const char variable_s_quoted[5] =
|
||||
+ { '\'', '%', variable_char, '\'', '\0' };
|
||||
+ const char variable_d_quoted[5] =
|
||||
+ { '"', '%', variable_char, '"', '\0' };
|
||||
+ char *cmd = NULL;
|
||||
+ char *masked_value = NULL;
|
||||
+ char *quoted_value = NULL;
|
||||
+ bool has_s_quotes;
|
||||
+ bool has_d_quotes;
|
||||
+ bool has_variable;
|
||||
+ bool has_variable_s_quoted;
|
||||
+ bool has_variable_d_quoted;
|
||||
+ bool modified = false;
|
||||
+ bool masked = false;
|
||||
+ bool mixed_fallback = false;
|
||||
+ bool ok;
|
||||
+
|
||||
+ /*
|
||||
+ * The unsafe_characters argument should contain
|
||||
+ * single and double quotes.
|
||||
+ * Otherwise We can't safely handle this.
|
||||
+ */
|
||||
+ SMB_ASSERT(unsafe_characters != NULL);
|
||||
+ SMB_ASSERT(strchr(unsafe_characters, '\'') != NULL);
|
||||
+ SMB_ASSERT(strchr(unsafe_characters, '"') != NULL);
|
||||
+ SMB_ASSERT(strchr(unsafe_characters, '%') != NULL);
|
||||
+
|
||||
+ cmd = talloc_strdup(mem_ctx, orig_cmd);
|
||||
+ if (cmd == NULL) {
|
||||
+ TALLOC_FREE(frame);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ cmd = talloc_steal(frame, cmd);
|
||||
+
|
||||
+ has_variable = strstr(orig_cmd, variable) != NULL;
|
||||
+ if (!has_variable) {
|
||||
+ /*
|
||||
+ * Nothing to do...
|
||||
+ */
|
||||
+ goto done;
|
||||
+ }
|
||||
+ modified = true;
|
||||
+
|
||||
+ /*
|
||||
+ * Replace all unsafe characters as well as control
|
||||
+ * characters.
|
||||
+ *
|
||||
+ * Note that we start with masked_value = "%u"
|
||||
+ * and then replace "%u" with unsafe_value,
|
||||
+ * as a result we have a masked version of
|
||||
+ * unsafe_value.
|
||||
+ *
|
||||
+ * And don't allow option injected like
|
||||
+ *
|
||||
+ * '-h value'
|
||||
+ * '--help value'
|
||||
+ *
|
||||
+ */
|
||||
+ masked_value = talloc_strdup(frame, variable);
|
||||
+ if (masked_value == NULL) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+ ok = realloc_string_sub_raw(&masked_value,
|
||||
+ variable,
|
||||
+ unsafe_value,
|
||||
+ false, /* replace_once */
|
||||
+ false, /* allow_trailing_dollar */
|
||||
+ unsafe_characters,
|
||||
+ safe_character);
|
||||
+ if (!ok) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+ if (masked_value[0] == '-') {
|
||||
+ masked_value[0] = safe_character;
|
||||
+ }
|
||||
+ masked = strcmp(masked_value, unsafe_value) != 0;
|
||||
+
|
||||
+retry:
|
||||
+
|
||||
+ has_s_quotes = strchr(cmd, '\'') != NULL;
|
||||
+ has_d_quotes = strchr(cmd, '"') != NULL;
|
||||
+ has_variable = strstr(cmd, variable) != NULL;
|
||||
+ has_variable_s_quoted = strstr(cmd, variable_s_quoted) != NULL;
|
||||
+ has_variable_d_quoted = strstr(cmd, variable_d_quoted) != NULL;
|
||||
+
|
||||
+ if (has_variable_s_quoted) {
|
||||
+ /*
|
||||
+ * In smb.conf we have something like
|
||||
+ *
|
||||
+ * some script = /usr/bin/script '%u'
|
||||
+ *
|
||||
+ * It is safe to replace '%u' (or '%J' etc, depending
|
||||
+ * on variable_char) with '<masked_value>' if
|
||||
+ * masked_value does not contain single quotes. We
|
||||
+ * have checked that.
|
||||
+ */
|
||||
+
|
||||
+ if (quoted_value == NULL) {
|
||||
+ quoted_value = talloc_asprintf(frame, "'%s'",
|
||||
+ masked_value);
|
||||
+ if (quoted_value == NULL) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ok = realloc_string_sub_raw(&cmd,
|
||||
+ variable_s_quoted,
|
||||
+ quoted_value,
|
||||
+ false, /* replace_once */
|
||||
+ false, /* allow_trailing_dollar */
|
||||
+ NULL, /* unsafe_characters */
|
||||
+ '\0'); /* safe_character */
|
||||
+ if (!ok) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ if (has_variable_d_quoted && !has_s_quotes) {
|
||||
+ /*
|
||||
+ * replace the "%u"
|
||||
+ *
|
||||
+ * some script = /usr/bin/script "%u"
|
||||
+ *
|
||||
+ * with '%u' and try the '%u' -> 'variable' substitution
|
||||
+ * again.
|
||||
+ */
|
||||
+
|
||||
+ ok = realloc_string_sub_raw(&cmd,
|
||||
+ variable_d_quoted,
|
||||
+ variable_s_quoted,
|
||||
+ false, /* replace_once */
|
||||
+ false, /* allow_trailing_dollar */
|
||||
+ NULL, /* unsafe_characters */
|
||||
+ '\0'); /* safe_character */
|
||||
+ if (!ok) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ if (has_variable && !has_s_quotes && !has_d_quotes) {
|
||||
+ /*
|
||||
+ * In this case:
|
||||
+ *
|
||||
+ * some script = /usr/bin/script %u
|
||||
+ *
|
||||
+ * we can safely substitute %u -> '%u' and try the
|
||||
+ * single quote test again.
|
||||
+ */
|
||||
+
|
||||
+ ok = realloc_string_sub_raw(&cmd,
|
||||
+ variable,
|
||||
+ variable_s_quoted,
|
||||
+ false, /* replace_once */
|
||||
+ false, /* allow_trailing_dollar */
|
||||
+ NULL, /* unsafe_characters */
|
||||
+ '\0'); /* safe_character */
|
||||
+ if (!ok) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ if (has_variable) {
|
||||
+ /*
|
||||
+ * There are single or double quotes, but not tightly
|
||||
+ * bound around a %u.
|
||||
+ *
|
||||
+ * Or there's a mix of single and double quotes.
|
||||
+ *
|
||||
+ * We just use a generic fallback value.
|
||||
+ * and let the caller warn about this
|
||||
+ * and give the admin a hind to fix the smb.conf
|
||||
+ * option.
|
||||
+ */
|
||||
+ mixed_fallback = true;
|
||||
+
|
||||
+ ok = realloc_string_sub_raw(&cmd,
|
||||
+ variable,
|
||||
+ fallback_value,
|
||||
+ false, /* replace_once */
|
||||
+ false, /* allow_trailing_dollar */
|
||||
+ NULL, /* unsafe_characters */
|
||||
+ '\0'); /* safe_character */
|
||||
+ if (!ok) {
|
||||
+ goto nomem;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ *_modified = modified;
|
||||
+ *_masked = masked;
|
||||
+ *_mixed_fallback = mixed_fallback;
|
||||
+ cmd = talloc_steal(mem_ctx, cmd);
|
||||
+ TALLOC_FREE(frame);
|
||||
+ return cmd;
|
||||
+
|
||||
+nomem:
|
||||
+ *_modified = false;
|
||||
+ *_masked = false;
|
||||
+ *_mixed_fallback = false;
|
||||
+ TALLOC_FREE(frame);
|
||||
+ return NULL;
|
||||
+}
|
||||
+#endif /* ! SAMBA_UTIL_CORE_ONLY */
|
||||
diff --git a/lib/util/substitute.h b/lib/util/substitute.h
|
||||
index 41f56c73ba2c..b8205055da1e 100644
|
||||
--- a/lib/util/substitute.h
|
||||
+++ b/lib/util/substitute.h
|
||||
@@ -83,4 +83,21 @@ char *talloc_all_string_sub(TALLOC_CTX *ctx,
|
||||
const char *src,
|
||||
const char *pattern,
|
||||
const char *insert);
|
||||
+
|
||||
+#ifndef SAMBA_UTIL_CORE_ONLY
|
||||
+bool talloc_string_sub_mixed_quoting(const char *full_cmd, char variable_char);
|
||||
+
|
||||
+char *talloc_string_sub_unsafe(TALLOC_CTX *mem_ctx,
|
||||
+ const char *orig_cmd,
|
||||
+ char variable_char,
|
||||
+ const char *unsafe_value,
|
||||
+ const char *unsafe_characters,
|
||||
+ char safe_character,
|
||||
+ const char *fallback_value,
|
||||
+ bool *_modified,
|
||||
+ bool *_masked,
|
||||
+ bool *_mixed_fallback);
|
||||
+
|
||||
+#endif /* ! SAMBA_UTIL_CORE_ONLY */
|
||||
+
|
||||
#endif /* _SAMBA_SUBSTITUTE_H_ */
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
From 6dce1833a5d27f82a9b133601ce7f749f3be08ec Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:56:21 +0200
|
||||
Subject: [PATCH] CVE-2026-4408: lib/util: introduce
|
||||
strstr_for_invalid_account_characters()
|
||||
|
||||
This splits out the logic from samaccountname_bad_chars_check()
|
||||
in source4/dsdb/samdb/ldb_modules/samldb.c, this will be used
|
||||
in other places soon.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/6dce1833a5d27f82a9b133601ce7f749f3be08ec]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 6dce1833a5d27f82a9b133601ce7f749f3be08ec)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/samba_util.h | 9 +++++++++
|
||||
lib/util/util_str.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 47 insertions(+)
|
||||
|
||||
diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
|
||||
index 03dee5c61379..ea741b51c58f 100644
|
||||
--- a/lib/util/samba_util.h
|
||||
+++ b/lib/util/samba_util.h
|
||||
@@ -303,6 +303,15 @@ _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean);
|
||||
*/
|
||||
_PUBLIC_ bool conv_str_bool(const char * str, bool * val);
|
||||
|
||||
+/**
|
||||
+ * Returns a pointer to the first invalid character in name.
|
||||
+ *
|
||||
+ * Passing a NULL pointer as name is not allowed!
|
||||
+ *
|
||||
+ * This returns NULL for a valid account name.
|
||||
+ **/
|
||||
+_PUBLIC_ const char *strstr_for_invalid_account_characters(const char *name);
|
||||
+
|
||||
/**
|
||||
* Convert a size specification like 16K into an integral number of bytes.
|
||||
**/
|
||||
diff --git a/lib/util/util_str.c b/lib/util/util_str.c
|
||||
index 7c1d15dbeb0b..c4eda4f49f38 100644
|
||||
--- a/lib/util/util_str.c
|
||||
+++ b/lib/util/util_str.c
|
||||
@@ -305,3 +305,41 @@ _PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+_PUBLIC_ const char *strstr_for_invalid_account_characters(const char *name)
|
||||
+{
|
||||
+ /*
|
||||
+ * Return a pointer to the first invalid character in the
|
||||
+ * sAMAccountName, or NULL if the whole name is valid.
|
||||
+ *
|
||||
+ * The rules here are based on
|
||||
+ *
|
||||
+ * https://social.technet.microsoft.com/wiki/contents/articles/11216.active-directory-requirements-for-creating-objects.aspx
|
||||
+ */
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; name[i] != '\0'; i++) {
|
||||
+ uint8_t c = name[i];
|
||||
+ const char *p = NULL;
|
||||
+
|
||||
+ if (iscntrl(c)) {
|
||||
+ return &name[i];
|
||||
+ }
|
||||
+
|
||||
+ p = strchr("\"[]:;|=+*?<>/\\,", c);
|
||||
+ if (p != NULL) {
|
||||
+ return &name[i];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (i == 0) {
|
||||
+ return &name[i];
|
||||
+ }
|
||||
+
|
||||
+ if (name[i - 1] == '.') {
|
||||
+ i -= 1;
|
||||
+ return &name[i];
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
From 8f28ca0b8abccf30f479133cc78f9a72500ab366 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Mon, 11 May 2026 20:21:36 +0200
|
||||
Subject: [PATCH] CVE-2026-4408: s3:samr-server: only allow
|
||||
_samr_ValidatePassword as DC
|
||||
|
||||
This is only supported with 'rpc start on demand helpers = no',
|
||||
as it needs ncacn_ip_tcp, but we better also restrict it to DCs.
|
||||
|
||||
Maybe only FreeIPA needs it as NT4 didn't support ncacn_ip_tcp.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/8f28ca0b8abccf30f479133cc78f9a72500ab366]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 8f28ca0b8abccf30f479133cc78f9a72500ab366)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/rpc_server/samr/srv_samr_nt.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/source3/rpc_server/samr/srv_samr_nt.c b/source3/rpc_server/samr/srv_samr_nt.c
|
||||
index e0d0875bd5da..3937dbe3f32e 100644
|
||||
--- a/source3/rpc_server/samr/srv_samr_nt.c
|
||||
+++ b/source3/rpc_server/samr/srv_samr_nt.c
|
||||
@@ -7500,6 +7500,14 @@ NTSTATUS _samr_ValidatePassword(struct pipes_struct *p,
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
+ if (lp_server_role() <= ROLE_DOMAIN_MEMBER) {
|
||||
+ /*
|
||||
+ * We only want this on DCs
|
||||
+ */
|
||||
+ p->fault_state = DCERPC_FAULT_ACCESS_DENIED;
|
||||
+ return NT_STATUS_ACCESS_DENIED;
|
||||
+ }
|
||||
+
|
||||
if (r->in.level < 1 || r->in.level > 3) {
|
||||
return NT_STATUS_INVALID_INFO_CLASS;
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
From 1c5146ddfc736e9d790bd91f3124c6fba6847bb3 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Wed, 18 Mar 2026 12:24:47 +0100
|
||||
Subject: [PATCH] CVE-2026-4408: s3:samr-server: deny, mask and/or single
|
||||
quote username to 'check password script'
|
||||
|
||||
We pass this on to the check password script, prevent remote command
|
||||
execution.
|
||||
|
||||
We now try to autodetect if we could implicitly use '%u' for the
|
||||
replacement and fallback to a fixed fallback username.
|
||||
|
||||
Admins should make use of SAMBA_CPS_ACCOUNT_NAME
|
||||
instead of passing '%u' to 'check password script'
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
Pair-Programmed-With: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/1c5146ddfc736e9d790bd91f3124c6fba6847bb3]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 1c5146ddfc736e9d790bd91f3124c6fba6847bb3)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/rpc_server/samr/srv_samr_chgpasswd.c | 110 +++++++++++++++++--
|
||||
1 file changed, 101 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
index 6c0c0da0cfc3..9afb8799aea0 100644
|
||||
--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
+++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "passdb.h"
|
||||
#include "auth.h"
|
||||
#include "lib/util/sys_rw.h"
|
||||
+#include "lib/util/util_str_escape.h"
|
||||
#include "librpc/rpc/dcerpc_samr.h"
|
||||
|
||||
#include "lib/crypto/gnutls_helpers.h"
|
||||
@@ -1008,27 +1009,118 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext)
|
||||
/***********************************************************
|
||||
************************************************************/
|
||||
|
||||
+static NTSTATUS check_password_complexity_internal(TALLOC_CTX *tosctx,
|
||||
+ const char *orig_cmd,
|
||||
+ const char *username,
|
||||
+ char **cmd_out)
|
||||
+{
|
||||
+ const char *fallback_username = "__CVE-2026-4408_FallbackUsername__";
|
||||
+ const char *inv = NULL;
|
||||
+ char *cmd = NULL;
|
||||
+ bool modified = false;
|
||||
+ bool masked = false;
|
||||
+ bool mixed_fallback = false;
|
||||
+
|
||||
+ *cmd_out = NULL;
|
||||
+
|
||||
+ if (username == NULL) {
|
||||
+ return NT_STATUS_INVALID_USER_PRINCIPAL_NAME;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * This catches invalid characters in account names
|
||||
+ * which might be problematic passing to a shell script.
|
||||
+ */
|
||||
+ inv = strstr_for_invalid_account_characters(username);
|
||||
+ if (inv != NULL) {
|
||||
+ char *le_username = log_escape(tosctx, username);
|
||||
+
|
||||
+ DBG_WARNING("username '%s' has invalid or dangerous characters\n",
|
||||
+ le_username);
|
||||
+
|
||||
+ TALLOC_FREE(le_username);
|
||||
+
|
||||
+ return NT_STATUS_INVALID_USER_PRINCIPAL_NAME;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * This masks the remaining unsafe characters which
|
||||
+ * are not already caught by strstr_for_invalid_account_characters()
|
||||
+ * with '_'.
|
||||
+ *
|
||||
+ * Then it replaces %u with an single quoted
|
||||
+ * and/or shell escaped version of the masked username.
|
||||
+ */
|
||||
+ cmd = talloc_string_sub_unsafe(tosctx,
|
||||
+ orig_cmd,
|
||||
+ 'u',
|
||||
+ username,
|
||||
+ STRING_SUB_UNSAFE_CHARACTERS,
|
||||
+ '_',
|
||||
+ fallback_username,
|
||||
+ &modified,
|
||||
+ &masked,
|
||||
+ &mixed_fallback);
|
||||
+ if (cmd == NULL) {
|
||||
+ return NT_STATUS_NO_MEMORY;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Now warn about unexpected values
|
||||
+ */
|
||||
+
|
||||
+ if (mixed_fallback) {
|
||||
+ D_WARNING("CVE-2026-4408: "
|
||||
+ "strange quoting in 'check password script', "
|
||||
+ "falling back to replace %%u with %s, "
|
||||
+ "use testparm to fix the configuration\n",
|
||||
+ fallback_username);
|
||||
+ D_WARNING("CVE-2026-4408: "
|
||||
+ "You should use '%%u', or SAMBA_CPS_ACCOUNT_NAME "
|
||||
+ "inside of 'check password script'.\n");
|
||||
+ } else if (masked) {
|
||||
+ char *le_username = log_escape(tosctx, username);
|
||||
+
|
||||
+ D_WARNING("CVE-2026-4408: "
|
||||
+ "replaced %%u with masked value instead of: %s\n",
|
||||
+ le_username);
|
||||
+ D_WARNING("CVE-2026-4408: "
|
||||
+ "You should use SAMBA_CPS_ACCOUNT_NAME inside "
|
||||
+ "'check password script' instead of %%u.\n");
|
||||
+
|
||||
+ TALLOC_FREE(le_username);
|
||||
+ }
|
||||
+
|
||||
+ *cmd_out = cmd;
|
||||
+ return NT_STATUS_OK;
|
||||
+}
|
||||
+
|
||||
+
|
||||
NTSTATUS check_password_complexity(const char *username,
|
||||
const char *fullname,
|
||||
const char *password,
|
||||
enum samPwdChangeReason *samr_reject_reason)
|
||||
{
|
||||
+ int check_ret;
|
||||
+ NTSTATUS status;
|
||||
TALLOC_CTX *tosctx = talloc_tos();
|
||||
const struct loadparm_substitution *lp_sub =
|
||||
loadparm_s3_global_substitution();
|
||||
- int check_ret;
|
||||
- char *cmd;
|
||||
+ const char *orig_cmd = NULL;
|
||||
+ char *cmd = NULL;
|
||||
|
||||
- /* Use external script to check password complexity */
|
||||
- if ((lp_check_password_script(tosctx, lp_sub) == NULL)
|
||||
- || (*(lp_check_password_script(tosctx, lp_sub)) == '\0')){
|
||||
+ orig_cmd = lp_check_password_script(tosctx, lp_sub);
|
||||
+ if (orig_cmd == NULL || orig_cmd[0] == '\0') {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
- cmd = talloc_string_sub(tosctx, lp_check_password_script(tosctx, lp_sub), "%u",
|
||||
- username);
|
||||
- if (!cmd) {
|
||||
- return NT_STATUS_PASSWORD_RESTRICTION;
|
||||
+ /* note we don't use 'fullname' or 'password' here */
|
||||
+ status = check_password_complexity_internal(tosctx,
|
||||
+ orig_cmd,
|
||||
+ username,
|
||||
+ &cmd);
|
||||
+ if (!NT_STATUS_IS_OK(status)) {
|
||||
+ return status;
|
||||
}
|
||||
|
||||
check_ret = setenv("SAMBA_CPS_ACCOUNT_NAME", username, 1);
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
From 67ad724e22f3724d5e07eaa8f25eb527aa417599 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Sat, 2 May 2026 22:12:38 +1200
|
||||
Subject: [PATCH] CVE-2026-4408: s3:samr-server: make
|
||||
check_password_complexity_internal() non-static, for easier testing
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/67ad724e22f3724d5e07eaa8f25eb527aa417599]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 67ad724e22f3724d5e07eaa8f25eb527aa417599)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/rpc_server/samr/srv_samr_chgpasswd.c | 8 ++++----
|
||||
source3/rpc_server/samr/srv_samr_util.h | 5 +++++
|
||||
2 files changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/source3/rpc_server/samr/srv_samr_chgpasswd.c b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
index 9afb8799aea0..3f48da47a5bd 100644
|
||||
--- a/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
+++ b/source3/rpc_server/samr/srv_samr_chgpasswd.c
|
||||
@@ -1009,10 +1009,10 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext)
|
||||
/***********************************************************
|
||||
************************************************************/
|
||||
|
||||
-static NTSTATUS check_password_complexity_internal(TALLOC_CTX *tosctx,
|
||||
- const char *orig_cmd,
|
||||
- const char *username,
|
||||
- char **cmd_out)
|
||||
+NTSTATUS check_password_complexity_internal(TALLOC_CTX *tosctx,
|
||||
+ const char *orig_cmd,
|
||||
+ const char *username,
|
||||
+ char **cmd_out)
|
||||
{
|
||||
const char *fallback_username = "__CVE-2026-4408_FallbackUsername__";
|
||||
const char *inv = NULL;
|
||||
diff --git a/source3/rpc_server/samr/srv_samr_util.h b/source3/rpc_server/samr/srv_samr_util.h
|
||||
index 5e839ac77c01..a3a22012858b 100644
|
||||
--- a/source3/rpc_server/samr/srv_samr_util.h
|
||||
+++ b/source3/rpc_server/samr/srv_samr_util.h
|
||||
@@ -79,6 +79,11 @@ NTSTATUS pass_oem_change(char *user, const char *rhost,
|
||||
uchar password_encrypted_with_nt_hash[516],
|
||||
const uchar old_nt_hash_encrypted[16],
|
||||
enum samPwdChangeReason *reject_reason);
|
||||
+
|
||||
+NTSTATUS check_password_complexity_internal(TALLOC_CTX *mem_ctx,
|
||||
+ const char *_orig_cmd,
|
||||
+ const char *username,
|
||||
+ char **cmd_out);
|
||||
NTSTATUS check_password_complexity(const char *username,
|
||||
const char *fullname,
|
||||
const char *password,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,422 @@
|
||||
From 266cd3dc063fdb88a0d0468e8d6f85d6abdecc04 Mon Sep 17 00:00:00 2001
|
||||
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Date: Sat, 2 May 2026 22:14:43 +1200
|
||||
Subject: [PATCH] CVE-2026-4408: s3:torture: tests for password
|
||||
complexity scripts
|
||||
|
||||
This tries to demonstrate the new logic for %u in
|
||||
'check password script'.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/266cd3dc063fdb88a0d0468e8d6f85d6abdecc04]
|
||||
|
||||
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
|
||||
|
||||
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
(cherry picked from commit 266cd3dc063fdb88a0d0468e8d6f85d6abdecc04)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
selftest/tests.py | 2 +
|
||||
source3/torture/test_rpc_samr.c | 358 ++++++++++++++++++++++++++++++++
|
||||
source3/torture/wscript_build | 6 +
|
||||
3 files changed, 366 insertions(+)
|
||||
create mode 100644 source3/torture/test_rpc_samr.c
|
||||
|
||||
diff --git a/selftest/tests.py b/selftest/tests.py
|
||||
index 71634191dd15..817c19aa1249 100644
|
||||
--- a/selftest/tests.py
|
||||
+++ b/selftest/tests.py
|
||||
@@ -575,6 +575,8 @@ plantestsuite("samba.unittests.test_oLschema2ldif", "none",
|
||||
[os.path.join(bindir(), "default/source4/utils/oLschema2ldif/test_oLschema2ldif")])
|
||||
plantestsuite("samba.unittests.auth.sam", "none",
|
||||
[os.path.join(bindir(), "test_auth_sam")])
|
||||
+plantestsuite("samba.unittests.test_rpc_samr", "none",
|
||||
+ [os.path.join(bindir(), "test_rpc_samr")])
|
||||
if have_heimdal_support and not using_system_gssapi:
|
||||
plantestsuite("samba.unittests.auth.heimdal_gensec_unwrap_des", "none",
|
||||
[valgrindify(os.path.join(bindir(), "test_heimdal_gensec_unwrap_des"))])
|
||||
diff --git a/source3/torture/test_rpc_samr.c b/source3/torture/test_rpc_samr.c
|
||||
new file mode 100644
|
||||
index 000000000000..8d4f39852462
|
||||
--- /dev/null
|
||||
+++ b/source3/torture/test_rpc_samr.c
|
||||
@@ -0,0 +1,358 @@
|
||||
+
|
||||
+#include <stdarg.h>
|
||||
+#include <stddef.h>
|
||||
+#include <stdint.h>
|
||||
+#include <setjmp.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <cmocka.h>
|
||||
+#include "includes.h"
|
||||
+#include "talloc.h"
|
||||
+#include "libcli/util/ntstatus.h"
|
||||
+#include "../librpc/gen_ndr/samr.h"
|
||||
+#include "rpc_server/samr/srv_samr_util.h"
|
||||
+
|
||||
+/* set SAMR_DEBUG_VERBOSE to true to print more. */
|
||||
+#define SAMR_DEBUG_VERBOSE true
|
||||
+
|
||||
+#if SAMR_DEBUG_VERBOSE
|
||||
+#define debug_message(...) print_message(__VA_ARGS__)
|
||||
+#else
|
||||
+#define debug_message(...) /* debug_message */
|
||||
+#endif
|
||||
+
|
||||
+static int setup_talloc_context(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
+ *state = mem_ctx;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int teardown_talloc_context(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = *state;
|
||||
+ TALLOC_FREE(mem_ctx);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+struct cmd_expansion {
|
||||
+ const char *lp_cmd;
|
||||
+ const char *username;
|
||||
+ const char *result_cmd;
|
||||
+ NTSTATUS result_code;
|
||||
+};
|
||||
+
|
||||
+static struct cmd_expansion expansions[] = {
|
||||
+ {
|
||||
+ "/bin/echo '%u'",
|
||||
+ "bob",
|
||||
+ "/bin/echo 'bob'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob",
|
||||
+ "/bin/echo 'bob'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob'",
|
||||
+ "/bin/echo 'bob_'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob\'",
|
||||
+ "/bin/echo 'bob_'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob'''",
|
||||
+ "/bin/echo 'bob___'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob*",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "bob\"",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '%u",
|
||||
+ "bob bob bob",
|
||||
+ "/bin/echo '__CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo \"%u\"",
|
||||
+ " ",
|
||||
+ "/bin/echo ' '",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo \"--uu=%u\"",
|
||||
+ "bob",
|
||||
+ "/bin/echo \"--uu=__CVE-2026-4408_FallbackUsername__\"",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo \"--uu=%u\"",
|
||||
+ "bob !0",
|
||||
+ "/bin/echo \"--uu=__CVE-2026-4408_FallbackUsername__\"",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "!0",
|
||||
+ "/bin/echo '!0'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo \"--uu=%u\"",
|
||||
+ "bob \\",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu='%u'",
|
||||
+ "bob >> x",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '--uu=%u\"",
|
||||
+ "bob",
|
||||
+ "/bin/echo '--uu=__CVE-2026-4408_FallbackUsername__\"",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu='%u'",
|
||||
+ "bob",
|
||||
+ "/bin/echo --uu='bob'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu'=%u'",
|
||||
+ "bob",
|
||||
+ "/bin/echo --uu'=__CVE-2026-4408_FallbackUsername__'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu'=%u'",
|
||||
+ "`ls`",
|
||||
+ "/bin/echo --uu'=__CVE-2026-4408_FallbackUsername__'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu'=%u'",
|
||||
+ "$(ls)",
|
||||
+ "/bin/echo --uu'=__CVE-2026-4408_FallbackUsername__'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu='%u'",
|
||||
+ "$(ls)",
|
||||
+ "/bin/echo --uu='_(ls)'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu=\"'%u'\"",
|
||||
+ "bob",
|
||||
+ "/bin/echo --uu=\"'bob'\"",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu='%u' --yy='%u' '%u' %u",
|
||||
+ "bob",
|
||||
+ "/bin/echo --uu='bob' --yy='bob' 'bob' __CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo --uu=%u%u'' %user 50%u",
|
||||
+ "bob",
|
||||
+ "/bin/echo --uu=__CVE-2026-4408_FallbackUsername____CVE-2026-4408_FallbackUsername__'' __CVE-2026-4408_FallbackUsername__ser 50__CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "!!",
|
||||
+ "/bin/echo '!!'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ ">xxx",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "\\",
|
||||
+ NULL,
|
||||
+ NT_STATUS_INVALID_USER_PRINCIPAL_NAME
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "3",
|
||||
+ "/bin/echo '3'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '%u'",
|
||||
+ "3$",
|
||||
+ "/bin/echo '3_'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '%u'",
|
||||
+ "comp$",
|
||||
+ "/bin/echo 'comp_'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '%u'",
|
||||
+ "3$3",
|
||||
+ "/bin/echo '3_3'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo '%u'",
|
||||
+ "q $3",
|
||||
+ "/bin/echo 'q _3'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s '%u' %u",
|
||||
+ "āāā",
|
||||
+ "/bin/echo -s 'āāā' __CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s '%u' %u",
|
||||
+ "-āāā",
|
||||
+ "/bin/echo -s '_āāā' __CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s %u",
|
||||
+ "āāā",
|
||||
+ "/bin/echo -s 'āāā'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s %u",
|
||||
+ "a -a",
|
||||
+ "/bin/echo -s 'a -a'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s=%u %u",
|
||||
+ "ā -a",
|
||||
+ "/bin/echo -s='ā -a' 'ā -a'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -s=\"%u %u\"",
|
||||
+ "ā -a",
|
||||
+ "/bin/echo -s=\"__CVE-2026-4408_FallbackUsername__ __CVE-2026-4408_FallbackUsername__\"",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -m='fridge' %u",
|
||||
+ "ā -x -ß",
|
||||
+ "/bin/echo -m='fridge' __CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo -m='fridge' %u",
|
||||
+ "-ā -a",
|
||||
+ "/bin/echo -m='fridge' __CVE-2026-4408_FallbackUsername__",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "-n",
|
||||
+ "/bin/echo '_n'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+ {
|
||||
+ "/bin/echo %u",
|
||||
+ "o'clock",
|
||||
+ "/bin/echo 'o_clock'",
|
||||
+ NT_STATUS_OK
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void test_expansions(void **state)
|
||||
+{
|
||||
+ TALLOC_CTX *mem_ctx = *state;
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(expansions); i++) {
|
||||
+ struct cmd_expansion t = expansions[i];
|
||||
+ char *result_cmd = NULL;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ status = check_password_complexity_internal(mem_ctx,
|
||||
+ t.lp_cmd,
|
||||
+ t.username,
|
||||
+ &result_cmd);
|
||||
+ if (NT_STATUS_IS_OK(t.result_code) && NT_STATUS_IS_OK(status)) {
|
||||
+ int cmp;
|
||||
+
|
||||
+ cmp = strcmp(t.result_cmd, result_cmd);
|
||||
+ if (cmp == 0) {
|
||||
+ debug_message("[%zu] «%s» «%s» -> «%s», nstatus %s; AS EXPECTED\n",
|
||||
+ i, t.lp_cmd,
|
||||
+ t.username,
|
||||
+ result_cmd,
|
||||
+ nt_errstr(status));
|
||||
+ } else {
|
||||
+ debug_message("[%zu] «%s» «%s», nstatus %s; "
|
||||
+ "expected «%s» got «%s»\033[1;31m BAD! \033[0m\n",
|
||||
+ i, t.lp_cmd,
|
||||
+ t.username,
|
||||
+ nt_errstr(status),
|
||||
+ t.result_cmd,
|
||||
+ result_cmd);
|
||||
+ }
|
||||
+ assert_int_equal(cmp, 0);
|
||||
+ } else if (NT_STATUS_EQUAL(status, t.result_code)) {
|
||||
+ debug_message("[%zu] «%s» «%s», nstatus %s FAILED AS EXPECTED\n",
|
||||
+ i, t.lp_cmd,
|
||||
+ t.username,
|
||||
+ nt_errstr(status));
|
||||
+ } else {
|
||||
+ debug_message("[%zu] «%s» «%s» -> «%s», nstatus %s; "
|
||||
+ "EXPECTED result «%s» ntstatus %s; \033[1;31m BAD! \033[0m\n",
|
||||
+ i, t.lp_cmd,
|
||||
+ t.username,
|
||||
+ result_cmd,
|
||||
+ nt_errstr(status),
|
||||
+ t.result_cmd,
|
||||
+ nt_errstr(t.result_code));
|
||||
+ assert_int_equal(true, false);
|
||||
+ }
|
||||
+ }
|
||||
+ debug_message("ALL correct\n");
|
||||
+}
|
||||
+
|
||||
+int main(void)
|
||||
+{
|
||||
+ const struct CMUnitTest tests[] = {
|
||||
+ cmocka_unit_test(test_expansions),
|
||||
+ };
|
||||
+ if (!isatty(1)) {
|
||||
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
|
||||
+ }
|
||||
+ return cmocka_run_group_tests(tests,
|
||||
+ setup_talloc_context,
|
||||
+ teardown_talloc_context);
|
||||
+}
|
||||
diff --git a/source3/torture/wscript_build b/source3/torture/wscript_build
|
||||
index 1d2520099e35..d04008b3df17 100644
|
||||
--- a/source3/torture/wscript_build
|
||||
+++ b/source3/torture/wscript_build
|
||||
@@ -133,3 +133,9 @@ bld.SAMBA3_BINARY('vfstest',
|
||||
SMBREADLINE
|
||||
''',
|
||||
for_selftest=True)
|
||||
+
|
||||
+bld.SAMBA3_BINARY('test_rpc_samr',
|
||||
+ source='test_rpc_samr.c',
|
||||
+ deps='''RPC_SERVICE cmocka
|
||||
+ ''',
|
||||
+ for_selftest=True)
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
From 65a9ac413b03eefc7a48d5536e54177319ca30e3 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Fri, 8 May 2026 23:27:35 +0200
|
||||
Subject: [PATCH] CVE-2026-4408: s3:testparm: warn about 'check password
|
||||
script' %u usage
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/65a9ac413b03eefc7a48d5536e54177319ca30e3]
|
||||
|
||||
Backport Changes:
|
||||
- Adjusted context for Samba 4.19.9 do_global_checks() because the
|
||||
surrounding global-check order differs from the upstream 4.22 patch.
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 65a9ac413b03eefc7a48d5536e54177319ca30e3)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/utils/testparm.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c
|
||||
index 02280595d2a0..1a6eb93a2e6d 100644
|
||||
--- a/source3/utils/testparm.c
|
||||
+++ b/source3/utils/testparm.c
|
||||
@@ -277,6 +277,7 @@ static int do_global_checks(void)
|
||||
const char *socket_options;
|
||||
const struct loadparm_substitution *lp_sub =
|
||||
loadparm_s3_global_substitution();
|
||||
+ const char *check_pw_script = NULL;
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
@@ -699,6 +700,17 @@ static int do_global_checks(void)
|
||||
"CVE-2022-37966\n\n");
|
||||
}
|
||||
|
||||
+ check_pw_script = lp_check_password_script(talloc_tos(), lp_sub);
|
||||
+ if (talloc_string_sub_mixed_quoting(check_pw_script, 'u')) {
|
||||
+ fprintf(stderr,
|
||||
+ "WARNING: You are using 'check password script' "
|
||||
+ "with mixed quoting and %%u.\n"
|
||||
+ "CVE-2026-4408 changed the way %%u substitution works. \n"
|
||||
+ "You should use the SAMBA_CPS_ACCOUNT_NAME "
|
||||
+ "environment variable exported to the script, or\n"
|
||||
+ "at least use single quotes (directly) around '%%u'.\n\n");
|
||||
+ }
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
@@ -0,0 +1,52 @@
|
||||
From 640f18d1a642264a9777f933dfaae78db6918a5f Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Mon, 11 May 2026 13:52:52 +0200
|
||||
Subject: [PATCH] CVE-2026-4408: docs-xml/smbdotconf: clarify '%u' in
|
||||
'check password script'
|
||||
|
||||
Admins should use SAMBA_CPS_ACCOUNT_NAME.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/640f18d1a642264a9777f933dfaae78db6918a5f]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 640f18d1a642264a9777f933dfaae78db6918a5f)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
docs-xml/smbdotconf/security/checkpasswordscript.xml | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/docs-xml/smbdotconf/security/checkpasswordscript.xml b/docs-xml/smbdotconf/security/checkpasswordscript.xml
|
||||
index 18aa2c6d290e..dd162d89f08a 100644
|
||||
--- a/docs-xml/smbdotconf/security/checkpasswordscript.xml
|
||||
+++ b/docs-xml/smbdotconf/security/checkpasswordscript.xml
|
||||
@@ -20,8 +20,8 @@
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
- SAMBA_CPS_ACCOUNT_NAME is always present and contains the sAMAccountName of user,
|
||||
- the is the same as the %u substitutions in the none AD DC case.
|
||||
+ SAMBA_CPS_ACCOUNT_NAME is always present and contains the sAMAccountName of user.
|
||||
+ It is the same as the '%u' substitutions in the non AD DC case.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>
|
||||
@@ -33,6 +33,12 @@
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
+ <para>Even on a non AD DC SAMBA_CPS_ACCOUNT_NAME is the preferred way to access the
|
||||
+ account name, as it contains the raw value provided by the client. If that's not
|
||||
+ possible you should use single quotes (directly) around %u, e.g. /path/to/somescript '%u',
|
||||
+ see CVE-2026-4408 for more details.
|
||||
+ </para>
|
||||
+
|
||||
<para>Note: In the example directory is a sample program called <command moreinfo="none">crackcheck</command>
|
||||
that uses cracklib to check the password quality.</para>
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
From 76dcb30911c22d92ca79e9034656b691a2d51df4 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:20:15 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: remove unused
|
||||
talloc_strdup(insert) from talloc_string_sub2()
|
||||
|
||||
The insert string is not modified, so we do not need to copy it.
|
||||
|
||||
This will simplify further changes.
|
||||
|
||||
Review with: git show --patience
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/76dcb30911c22d92ca79e9034656b691a2d51df4]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 76dcb30911c22d92ca79e9034656b691a2d51df4)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 57 +++++++++++++++++++------------------------
|
||||
1 file changed, 25 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index 26362ca77b2c..4a0c58ab3a7f 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -157,7 +157,7 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
bool replace_once,
|
||||
bool allow_trailing_dollar)
|
||||
{
|
||||
- char *p, *in;
|
||||
+ char *p;
|
||||
char *s;
|
||||
char *string;
|
||||
ssize_t ls,lp,li,ld, i;
|
||||
@@ -175,22 +175,32 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
|
||||
s = string;
|
||||
|
||||
- in = talloc_strdup(mem_ctx, insert);
|
||||
- if (!in) {
|
||||
- DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
|
||||
- talloc_free(string);
|
||||
- return NULL;
|
||||
- }
|
||||
ls = (ssize_t)strlen(s);
|
||||
lp = (ssize_t)strlen(pattern);
|
||||
li = (ssize_t)strlen(insert);
|
||||
ld = li - lp;
|
||||
|
||||
- for (i=0;i<li;i++) {
|
||||
- switch (in[i]) {
|
||||
+ while ((p = strstr_m(s,pattern))) {
|
||||
+ if (ld > 0) {
|
||||
+ int offset = PTR_DIFF(s,string);
|
||||
+ string = (char *)talloc_realloc_size(mem_ctx, string,
|
||||
+ ls + ld + 1);
|
||||
+ if (!string) {
|
||||
+ DEBUG(0, ("talloc_string_sub: out of "
|
||||
+ "memory!\n"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ p = string + offset + (p - s);
|
||||
+ }
|
||||
+ if (li != lp) {
|
||||
+ memmove(p+li,p+lp,strlen(p+lp)+1);
|
||||
+ }
|
||||
+ for (i=0; i<li; i++) {
|
||||
+ switch (insert[i]) {
|
||||
case '$':
|
||||
- /* allow a trailing $
|
||||
- * (as in machine accounts) */
|
||||
+ /*
|
||||
+ * allow a trailing $ (as in machine accounts)
|
||||
+ */
|
||||
if (allow_trailing_dollar && (i == li - 1 )) {
|
||||
break;
|
||||
}
|
||||
@@ -204,34 +214,18 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
case '\r':
|
||||
case '\n':
|
||||
if (remove_unsafe_characters) {
|
||||
- in[i] = '_';
|
||||
- break;
|
||||
+ p[i] = '_';
|
||||
+ continue;
|
||||
}
|
||||
|
||||
FALL_THROUGH;
|
||||
default:
|
||||
/* ok */
|
||||
break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- while ((p = strstr_m(s,pattern))) {
|
||||
- if (ld > 0) {
|
||||
- int offset = PTR_DIFF(s,string);
|
||||
- string = (char *)talloc_realloc_size(mem_ctx, string,
|
||||
- ls + ld + 1);
|
||||
- if (!string) {
|
||||
- DEBUG(0, ("talloc_string_sub: out of "
|
||||
- "memory!\n"));
|
||||
- TALLOC_FREE(in);
|
||||
- return NULL;
|
||||
}
|
||||
- p = string + offset + (p - s);
|
||||
- }
|
||||
- if (li != lp) {
|
||||
- memmove(p+li,p+lp,strlen(p+lp)+1);
|
||||
+
|
||||
+ p[i] = insert[i];
|
||||
}
|
||||
- memcpy(p, in, li);
|
||||
s = p + li;
|
||||
ls += ld;
|
||||
|
||||
@@ -239,7 +233,6 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
break;
|
||||
}
|
||||
}
|
||||
- TALLOC_FREE(in);
|
||||
return string;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
From 3032b7efe9d2fd35081ec33d575d01f9ebf6725c Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:20:15 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: factor out a
|
||||
mask_unsafe_character() helper function
|
||||
|
||||
This moves the logic into a single place and
|
||||
makes if more flexible to be used with more
|
||||
values than STRING_SUB_UNSAFE_CHARACTERS.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/3032b7efe9d2fd35081ec33d575d01f9ebf6725c]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 3032b7efe9d2fd35081ec33d575d01f9ebf6725c)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 109 +++++++++++++++++++++---------------------
|
||||
lib/util/substitute.h | 6 ++-
|
||||
2 files changed, 60 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index 4a0c58ab3a7f..b9fe32e993ec 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -35,6 +35,33 @@
|
||||
* @brief Substitute utilities.
|
||||
**/
|
||||
|
||||
+static inline
|
||||
+char mask_unsafe_character(char in,
|
||||
+ bool is_last,
|
||||
+ bool allow_trailing_dollar,
|
||||
+ const char *unsafe_characters,
|
||||
+ char safe_out)
|
||||
+{
|
||||
+ const char *unsafe = NULL;
|
||||
+
|
||||
+ if (unsafe_characters == NULL) {
|
||||
+ return in;
|
||||
+ }
|
||||
+
|
||||
+ /* allow a trailing $ (as in machine accounts) */
|
||||
+ if (allow_trailing_dollar && is_last && in == '$') {
|
||||
+ return in;
|
||||
+ }
|
||||
+
|
||||
+ unsafe = strchr(unsafe_characters, in);
|
||||
+ if (unsafe != NULL) {
|
||||
+ return safe_out;
|
||||
+ }
|
||||
+
|
||||
+ /* ok */
|
||||
+ return in;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
Substitute a string for a pattern in another string. Make sure there is
|
||||
enough room!
|
||||
@@ -42,14 +69,16 @@
|
||||
This routine looks for pattern in s and replaces it with
|
||||
insert. It may do multiple replacements or just one.
|
||||
|
||||
- Any of " ; ' $ or ` in the insert string are replaced with _
|
||||
+ Any of STRING_SUB_UNSAFE_CHARACTERS in the insert string are replaced with _
|
||||
+
|
||||
if len==0 then the string cannot be extended. This is different from the old
|
||||
use of len==0 which was for no length checks to be done.
|
||||
**/
|
||||
|
||||
void string_sub(char *s, const char *pattern, const char *insert, size_t len)
|
||||
{
|
||||
- bool remove_unsafe_characters = true;
|
||||
+ const char *unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
|
||||
+ char safe_character = '_';
|
||||
char *p;
|
||||
size_t ls, lp, li, i;
|
||||
|
||||
@@ -76,26 +105,18 @@ void string_sub(char *s, const char *pattern, const char *insert, size_t len)
|
||||
memmove(p+li,p+lp,strlen(p+lp)+1);
|
||||
}
|
||||
for (i=0;i<li;i++) {
|
||||
- switch (insert[i]) {
|
||||
- case '$':
|
||||
- case '`':
|
||||
- case '"':
|
||||
- case '\'':
|
||||
- case ';':
|
||||
- case '%':
|
||||
- case '\r':
|
||||
- case '\n':
|
||||
- if ( remove_unsafe_characters ) {
|
||||
- p[i] = '_';
|
||||
- /* yes this break should be here
|
||||
- * since we want to fall throw if
|
||||
- * not replacing unsafe chars */
|
||||
- break;
|
||||
- }
|
||||
- FALL_THROUGH;
|
||||
- default:
|
||||
- p[i] = insert[i];
|
||||
- }
|
||||
+ /*
|
||||
+ * Without allow_trailing_dollar we don't
|
||||
+ * need to calculate is_last...
|
||||
+ */
|
||||
+ const bool is_last = false;
|
||||
+ const bool allow_trailing_dollar = false;
|
||||
+
|
||||
+ p[i] = mask_unsafe_character(insert[i],
|
||||
+ is_last,
|
||||
+ allow_trailing_dollar,
|
||||
+ unsafe_characters,
|
||||
+ safe_character);
|
||||
}
|
||||
s = p + li;
|
||||
ls = ls + li - lp;
|
||||
@@ -157,9 +178,11 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
bool replace_once,
|
||||
bool allow_trailing_dollar)
|
||||
{
|
||||
- char *p;
|
||||
- char *s;
|
||||
- char *string;
|
||||
+ const char *unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
|
||||
+ const char safe_character = '_';
|
||||
+ char *p = NULL,
|
||||
+ char *s = NULL;
|
||||
+ char *string = NULL;
|
||||
ssize_t ls,lp,li,ld, i;
|
||||
|
||||
if (!insert || !pattern || !*pattern || !src) {
|
||||
@@ -195,36 +218,14 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
if (li != lp) {
|
||||
memmove(p+li,p+lp,strlen(p+lp)+1);
|
||||
}
|
||||
- for (i=0; i<li; i++) {
|
||||
- switch (insert[i]) {
|
||||
- case '$':
|
||||
- /*
|
||||
- * allow a trailing $ (as in machine accounts)
|
||||
- */
|
||||
- if (allow_trailing_dollar && (i == li - 1 )) {
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- FALL_THROUGH;
|
||||
- case '`':
|
||||
- case '"':
|
||||
- case '\'':
|
||||
- case ';':
|
||||
- case '%':
|
||||
- case '\r':
|
||||
- case '\n':
|
||||
- if (remove_unsafe_characters) {
|
||||
- p[i] = '_';
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- FALL_THROUGH;
|
||||
- default:
|
||||
- /* ok */
|
||||
- break;
|
||||
- }
|
||||
+ for (i=0; i < li; i++) {
|
||||
+ bool is_last = (i == li - 1);
|
||||
|
||||
- p[i] = insert[i];
|
||||
+ p[i] = mask_unsafe_character(insert[i],
|
||||
+ is_last,
|
||||
+ allow_trailing_dollar,
|
||||
+ unsafe_characters,
|
||||
+ safe_character);
|
||||
}
|
||||
s = p + li;
|
||||
ls += ld;
|
||||
diff --git a/lib/util/substitute.h b/lib/util/substitute.h
|
||||
index 3134cfcdea54..e1a82859daca 100644
|
||||
--- a/lib/util/substitute.h
|
||||
+++ b/lib/util/substitute.h
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
+#define STRING_SUB_UNSAFE_CHARACTERS "$`\"';%\r\n"
|
||||
+
|
||||
/**
|
||||
Substitute a string for a pattern in another string. Make sure there is
|
||||
enough room!
|
||||
@@ -33,7 +35,9 @@
|
||||
This routine looks for pattern in s and replaces it with
|
||||
insert. It may do multiple replacements.
|
||||
|
||||
- Any of " ; ' $ or ` in the insert string are replaced with _
|
||||
+ Any of STRING_SUB_UNSAFE_CHARACTERS (see above) in the
|
||||
+ insert string are replaced with _
|
||||
+
|
||||
if len==0 then the string cannot be extended. This is different from the old
|
||||
use of len==0 which was for no length checks to be done.
|
||||
**/
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
From 3f24236a5000402de11d973527eb7d28fd30de19 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 30 Apr 2026 14:48:26 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: split out
|
||||
realloc_string_sub_raw()
|
||||
|
||||
This will allow realloc_string_sub2() to use it in order
|
||||
to have the logic in one place only.
|
||||
|
||||
And it will also allow adjacted callers to be
|
||||
more flexible.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/3f24236a5000402de11d973527eb7d28fd30de19]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 3f24236a5000402de11d973527eb7d28fd30de19)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 85 ++++++++++++++++++++++++++++++-------------
|
||||
lib/util/substitute.h | 18 +++++++++
|
||||
2 files changed, 78 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index b9fe32e993ec..465aea866055 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -171,32 +171,24 @@ _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, siz
|
||||
* talloc version of string_sub2.
|
||||
*/
|
||||
|
||||
-char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
- const char *pattern,
|
||||
- const char *insert,
|
||||
- bool remove_unsafe_characters,
|
||||
- bool replace_once,
|
||||
- bool allow_trailing_dollar)
|
||||
+bool realloc_string_sub_raw(char **_string,
|
||||
+ const char *pattern,
|
||||
+ const char *insert,
|
||||
+ bool replace_once,
|
||||
+ bool allow_trailing_dollar,
|
||||
+ const char *unsafe_characters,
|
||||
+ char safe_character)
|
||||
{
|
||||
- const char *unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
|
||||
- const char safe_character = '_';
|
||||
- char *p = NULL,
|
||||
+ char *p = NULL;
|
||||
char *s = NULL;
|
||||
char *string = NULL;
|
||||
ssize_t ls,lp,li,ld, i;
|
||||
|
||||
- if (!insert || !pattern || !*pattern || !src) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- string = talloc_strdup(mem_ctx, src);
|
||||
- if (string == NULL) {
|
||||
- DEBUG(0, ("talloc_string_sub2: "
|
||||
- "talloc_strdup failed\n"));
|
||||
- return NULL;
|
||||
+ if (!insert || !pattern || !*pattern || !_string|| !*_string) {
|
||||
+ return false;
|
||||
}
|
||||
|
||||
- s = string;
|
||||
+ s = string = *_string;
|
||||
|
||||
ls = (ssize_t)strlen(s);
|
||||
lp = (ssize_t)strlen(pattern);
|
||||
@@ -205,14 +197,13 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
|
||||
while ((p = strstr_m(s,pattern))) {
|
||||
if (ld > 0) {
|
||||
- int offset = PTR_DIFF(s,string);
|
||||
- string = (char *)talloc_realloc_size(mem_ctx, string,
|
||||
- ls + ld + 1);
|
||||
+ ptrdiff_t offset = PTR_DIFF(s,string);
|
||||
+ string = talloc_realloc(NULL, string, char, ls + ld + 1);
|
||||
if (!string) {
|
||||
- DEBUG(0, ("talloc_string_sub: out of "
|
||||
- "memory!\n"));
|
||||
- return NULL;
|
||||
+ DBG_ERR("out of memory(realloc)!\n");
|
||||
+ return false;
|
||||
}
|
||||
+ *_string = string;
|
||||
p = string + offset + (p - s);
|
||||
}
|
||||
if (li != lp) {
|
||||
@@ -234,6 +225,50 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+char *talloc_string_sub2(TALLOC_CTX *mem_ctx,
|
||||
+ const char *src,
|
||||
+ const char *pattern,
|
||||
+ const char *insert,
|
||||
+ bool remove_unsafe_characters,
|
||||
+ bool replace_once,
|
||||
+ bool allow_trailing_dollar)
|
||||
+{
|
||||
+ const char *unsafe_characters = NULL;
|
||||
+ char safe_character = '\0';
|
||||
+ char *string = NULL;
|
||||
+ bool ok;
|
||||
+
|
||||
+ if (!insert || !pattern || !*pattern || !src) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (remove_unsafe_characters) {
|
||||
+ unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
|
||||
+ safe_character = '_';
|
||||
+ }
|
||||
+
|
||||
+ string = talloc_strdup(mem_ctx, src);
|
||||
+ if (string == NULL) {
|
||||
+ DBG_ERR("out of memory, talloc_strdup(src)!\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ ok = realloc_string_sub_raw(&string,
|
||||
+ pattern,
|
||||
+ insert,
|
||||
+ replace_once,
|
||||
+ allow_trailing_dollar,
|
||||
+ unsafe_characters,
|
||||
+ safe_character);
|
||||
+ if (!ok) {
|
||||
+ TALLOC_FREE(string);
|
||||
+ DBG_ERR("out of memory, realloc_string_sub_raw()!\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
return string;
|
||||
}
|
||||
|
||||
diff --git a/lib/util/substitute.h b/lib/util/substitute.h
|
||||
index e1a82859daca..041a649fd181 100644
|
||||
--- a/lib/util/substitute.h
|
||||
+++ b/lib/util/substitute.h
|
||||
@@ -51,6 +51,24 @@ void string_sub(char *s,const char *pattern, const char *insert, size_t len);
|
||||
**/
|
||||
void all_string_sub(char *s,const char *pattern,const char *insert, size_t len);
|
||||
|
||||
+/*
|
||||
+ * If unsafe_characters is NULL all characters are allowed,
|
||||
+ * if unsafe_characters is not NULL all characters caught
|
||||
+ * by iscntrl() are also replaced by safe_character.
|
||||
+ *
|
||||
+ * *_string might be reallocated!
|
||||
+ *
|
||||
+ * On error *_string may still be reallocated and
|
||||
+ * may contain partial replacements.
|
||||
+ */
|
||||
+bool realloc_string_sub_raw(char **_string,
|
||||
+ const char *pattern,
|
||||
+ const char *insert,
|
||||
+ bool replace_once,
|
||||
+ bool allow_trailing_dollar,
|
||||
+ const char *unsafe_characters,
|
||||
+ char safe_character);
|
||||
+
|
||||
char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
|
||||
const char *pattern,
|
||||
const char *insert,
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
From 113ba24197ca4e5bd683951f99fa4553a4240e48 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Wed, 6 May 2026 17:23:39 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: s3:lib: fix potential
|
||||
memory leak in talloc_sub_basic()
|
||||
|
||||
This makes the code easier to understand...
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/113ba24197ca4e5bd683951f99fa4553a4240e48]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 113ba24197ca4e5bd683951f99fa4553a4240e48)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/lib/substitute.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c
|
||||
index 40eb15aee04b..5121fcaac1c4 100644
|
||||
--- a/source3/lib/substitute.c
|
||||
+++ b/source3/lib/substitute.c
|
||||
@@ -317,6 +317,7 @@ char *talloc_sub_basic(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
|
||||
tmp_ctx = talloc_stackframe();
|
||||
+ a_string = talloc_steal(tmp_ctx, a_string);
|
||||
|
||||
for (s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
|
||||
|
||||
@@ -478,6 +479,7 @@ error:
|
||||
TALLOC_FREE(a_string);
|
||||
|
||||
done:
|
||||
+ a_string = talloc_steal(mem_ctx, a_string);
|
||||
TALLOC_FREE(tmp_ctx);
|
||||
return a_string;
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
From c4a93471622e5d7f8e28073029f3ebfbe22b6288 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 21:11:27 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: s3:lib: let
|
||||
realloc_string_sub2() use realloc_string_sub_raw()
|
||||
|
||||
We don't need this logic more than once!
|
||||
|
||||
But we leave the strange calling convention of
|
||||
realloc_string_sub2(), where the caller it
|
||||
not allowed to use the passed pointer when
|
||||
NULL is returned...
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/c4a93471622e5d7f8e28073029f3ebfbe22b6288]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit c4a93471622e5d7f8e28073029f3ebfbe22b6288)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
source3/lib/substitute_generic.c | 81 ++++++++++----------------------
|
||||
1 file changed, 24 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/source3/lib/substitute_generic.c b/source3/lib/substitute_generic.c
|
||||
index 26c5ee761f8b..e0639f04eb8e 100644
|
||||
--- a/source3/lib/substitute_generic.c
|
||||
+++ b/source3/lib/substitute_generic.c
|
||||
@@ -37,71 +37,38 @@ char *realloc_string_sub2(char *string,
|
||||
bool remove_unsafe_characters,
|
||||
bool allow_trailing_dollar)
|
||||
{
|
||||
- char *p, *in;
|
||||
- char *s;
|
||||
- ssize_t ls,lp,li,ld, i;
|
||||
+ const char *unsafe_characters = NULL;
|
||||
+ char safe_character = '\0';
|
||||
+ bool ok;
|
||||
|
||||
if (!insert || !pattern || !*pattern || !string || !*string)
|
||||
return NULL;
|
||||
|
||||
- s = string;
|
||||
+ if (remove_unsafe_characters) {
|
||||
+ unsafe_characters = STRING_SUB_UNSAFE_CHARACTERS;
|
||||
+ safe_character = '_';
|
||||
+ }
|
||||
|
||||
- in = talloc_strdup(talloc_tos(), insert);
|
||||
- if (!in) {
|
||||
- DEBUG(0, ("realloc_string_sub: out of memory!\n"));
|
||||
+ ok = realloc_string_sub_raw(&string,
|
||||
+ pattern,
|
||||
+ insert,
|
||||
+ false, /* replace_once */
|
||||
+ allow_trailing_dollar,
|
||||
+ unsafe_characters,
|
||||
+ safe_character);
|
||||
+ if (!ok) {
|
||||
+ DBG_ERR("out of memory, realloc_string_sub_raw()!\n");
|
||||
+ /*
|
||||
+ * The calling convention of realloc_string_sub2()
|
||||
+ * is very strange regarding stale string pointers.
|
||||
+ *
|
||||
+ * It is assumed the given string was allocated
|
||||
+ * on talloc_tos(), so we just don't touch
|
||||
+ * it at all here...
|
||||
+ */
|
||||
return NULL;
|
||||
}
|
||||
- ls = (ssize_t)strlen(s);
|
||||
- lp = (ssize_t)strlen(pattern);
|
||||
- li = (ssize_t)strlen(insert);
|
||||
- ld = li - lp;
|
||||
- for (i=0;i<li;i++) {
|
||||
- switch (in[i]) {
|
||||
- case '$':
|
||||
- /* allow a trailing $
|
||||
- * (as in machine accounts) */
|
||||
- if (allow_trailing_dollar && (i == li - 1 )) {
|
||||
- break;
|
||||
- }
|
||||
- FALL_THROUGH;
|
||||
- case '`':
|
||||
- case '"':
|
||||
- case '\'':
|
||||
- case ';':
|
||||
- case '%':
|
||||
- case '\r':
|
||||
- case '\n':
|
||||
- if ( remove_unsafe_characters ) {
|
||||
- in[i] = '_';
|
||||
- break;
|
||||
- }
|
||||
- FALL_THROUGH;
|
||||
- default:
|
||||
- /* ok */
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
|
||||
- while ((p = strstr_m(s,pattern))) {
|
||||
- if (ld > 0) {
|
||||
- int offset = PTR_DIFF(s,string);
|
||||
- string = talloc_realloc(NULL, string, char, ls + ld + 1);
|
||||
- if (!string) {
|
||||
- DEBUG(0, ("realloc_string_sub: "
|
||||
- "out of memory!\n"));
|
||||
- talloc_free(in);
|
||||
- return NULL;
|
||||
- }
|
||||
- p = string + offset + (p - s);
|
||||
- }
|
||||
- if (li != lp) {
|
||||
- memmove(p+li,p+lp,strlen(p+lp)+1);
|
||||
- }
|
||||
- memcpy(p, in, li);
|
||||
- s = p + li;
|
||||
- ls += ld;
|
||||
- }
|
||||
- talloc_free(in);
|
||||
return string;
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
From 003ff9b49f65d8006330a018da6fe0169a6fdb48 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:21:08 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: let
|
||||
mask_unsafe_character() check all control characters
|
||||
|
||||
There's no reason to mask only \r and \n.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/003ff9b49f65d8006330a018da6fe0169a6fdb48]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 003ff9b49f65d8006330a018da6fe0169a6fdb48)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.c | 8 +++++++-
|
||||
lib/util/substitute.h | 6 +++---
|
||||
2 files changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/util/substitute.c b/lib/util/substitute.c
|
||||
index 465aea866055..30989927da72 100644
|
||||
--- a/lib/util/substitute.c
|
||||
+++ b/lib/util/substitute.c
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "replace.h"
|
||||
+#include "system/locale.h"
|
||||
#include "debug.h"
|
||||
#ifndef SAMBA_UTIL_CORE_ONLY
|
||||
#include "charset/charset.h"
|
||||
@@ -53,6 +54,10 @@ char mask_unsafe_character(char in,
|
||||
return in;
|
||||
}
|
||||
|
||||
+ if (iscntrl(in)) {
|
||||
+ return safe_out;
|
||||
+ }
|
||||
+
|
||||
unsafe = strchr(unsafe_characters, in);
|
||||
if (unsafe != NULL) {
|
||||
return safe_out;
|
||||
@@ -69,7 +74,8 @@ char mask_unsafe_character(char in,
|
||||
This routine looks for pattern in s and replaces it with
|
||||
insert. It may do multiple replacements or just one.
|
||||
|
||||
- Any of STRING_SUB_UNSAFE_CHARACTERS in the insert string are replaced with _
|
||||
+ Any of STRING_SUB_UNSAFE_CHARACTERS and any character
|
||||
+ caught by calling iscntrl() in the insert string are replaced with _
|
||||
|
||||
if len==0 then the string cannot be extended. This is different from the old
|
||||
use of len==0 which was for no length checks to be done.
|
||||
diff --git a/lib/util/substitute.h b/lib/util/substitute.h
|
||||
index 041a649fd181..b183d864671a 100644
|
||||
--- a/lib/util/substitute.h
|
||||
+++ b/lib/util/substitute.h
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
-#define STRING_SUB_UNSAFE_CHARACTERS "$`\"';%\r\n"
|
||||
+#define STRING_SUB_UNSAFE_CHARACTERS "$`\"';%"
|
||||
|
||||
/**
|
||||
Substitute a string for a pattern in another string. Make sure there is
|
||||
@@ -35,8 +35,8 @@
|
||||
This routine looks for pattern in s and replaces it with
|
||||
insert. It may do multiple replacements.
|
||||
|
||||
- Any of STRING_SUB_UNSAFE_CHARACTERS (see above) in the
|
||||
- insert string are replaced with _
|
||||
+ Any of STRING_SUB_UNSAFE_CHARACTERS (see above) and any character
|
||||
+ caught by calling iscntrl() in the insert string are replaced with _
|
||||
|
||||
if len==0 then the string cannot be extended. This is different from the old
|
||||
use of len==0 which was for no length checks to be done.
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From 5551dd76e92480625f00765f183d753dcb857894 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Thu, 23 Apr 2026 18:21:08 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: add more unsafe
|
||||
characters to STRING_SUB_UNSAFE_CHARACTERS
|
||||
|
||||
|&<> are unsafe characters for shell processing.
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/5551dd76e92480625f00765f183d753dcb857894]
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 5551dd76e92480625f00765f183d753dcb857894)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/substitute.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/util/substitute.h b/lib/util/substitute.h
|
||||
index b183d864671a..41f56c73ba2c 100644
|
||||
--- a/lib/util/substitute.h
|
||||
+++ b/lib/util/substitute.h
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
-#define STRING_SUB_UNSAFE_CHARACTERS "$`\"';%"
|
||||
+#define STRING_SUB_UNSAFE_CHARACTERS "$`\"';%|&<>"
|
||||
|
||||
/**
|
||||
Substitute a string for a pattern in another string. Make sure there is
|
||||
--
|
||||
2.43.0
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From 0cabcbd24cf2eec692b1a9642447e81c97cc90b7 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Metzmacher <metze@samba.org>
|
||||
Date: Fri, 8 May 2026 22:33:32 +0200
|
||||
Subject: [PATCH] CVE-2026-4480/CVE-2026-4408: lib/util: let log_escape()
|
||||
make use of iscntrl()
|
||||
|
||||
using iscntrl() also handles 0x7F (DEL).
|
||||
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16033
|
||||
BUG: https://bugzilla.samba.org/show_bug.cgi?id=16034
|
||||
|
||||
CVE: CVE-2026-4408
|
||||
Upstream-Status: Backport [https://gitlab.com/samba-team/samba/-/commit/0cabcbd24cf2eec692b1a9642447e81c97cc90b7]
|
||||
|
||||
Backport Changes:
|
||||
- Adjusted context for Samba 4.19.9 where encoded_length() still takes char;
|
||||
use unsigned char so iscntrl() receives the same safe input type as upstream.
|
||||
|
||||
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
||||
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
|
||||
(cherry picked from commit 0cabcbd24cf2eec692b1a9642447e81c97cc90b7)
|
||||
Signed-off-by: Ashishkumar Parmar <asparmar@cisco.com>
|
||||
---
|
||||
lib/util/util_str_escape.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/util/util_str_escape.c b/lib/util/util_str_escape.c
|
||||
index 21f6130a3d60..c6d7a0c9e77a 100644
|
||||
--- a/lib/util/util_str_escape.c
|
||||
+++ b/lib/util/util_str_escape.c
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "replace.h"
|
||||
+#include "system/locale.h"
|
||||
#include "lib/util/debug.h"
|
||||
#include "lib/util/util_str_escape.h"
|
||||
|
||||
@@ -26,9 +27,9 @@
|
||||
* Calculate the encoded length of a character for log_escape
|
||||
*
|
||||
*/
|
||||
-static size_t encoded_length(char c)
|
||||
+static size_t encoded_length(unsigned char c)
|
||||
{
|
||||
- if (c != '\\' && c > 0x1F) {
|
||||
+ if (c != '\\' && !iscntrl(c)) {
|
||||
return 1;
|
||||
} else {
|
||||
switch (c) {
|
||||
@@ -79,7 +80,7 @@ char *log_escape(TALLOC_CTX *frame, const char *in)
|
||||
c = in;
|
||||
e = encoded;
|
||||
while (*c) {
|
||||
- if (*c != '\\' && *c > 0x1F) {
|
||||
+ if (*c != '\\' && !iscntrl((unsigned char)(*c))) {
|
||||
*e++ = *c++;
|
||||
} else {
|
||||
switch (*c) {
|
||||
--
|
||||
2.43.0
|
||||
@@ -26,6 +26,24 @@ SRC_URI = "${SAMBA_MIRROR}/stable/samba-${PV}.tar.gz \
|
||||
file://0007-Deleted-settiong-of-python-to-fix-the-install-confli.patch \
|
||||
file://CVE-2026-3012_p1.patch \
|
||||
file://CVE-2026-3012_p2.patch \
|
||||
file://CVE-2026-4408_p1.patch \
|
||||
file://CVE-2026-4408_p2.patch \
|
||||
file://CVE-2026-4408_p3.patch \
|
||||
file://CVE-2026-4408_p4.patch \
|
||||
file://CVE-2026-4408_p5.patch \
|
||||
file://CVE-2026-4408_p6.patch \
|
||||
file://CVE-2026-4408_p7.patch \
|
||||
file://CVE-2026-4408_p8.patch \
|
||||
file://CVE-2026-4408_p9.patch \
|
||||
file://CVE-2026-4408_p10.patch \
|
||||
file://CVE-2026-4408_p11.patch \
|
||||
file://CVE-2026-4408_p12.patch \
|
||||
file://CVE-2026-4408_p13.patch \
|
||||
file://CVE-2026-4408_p14.patch \
|
||||
file://CVE-2026-4408_p15.patch \
|
||||
file://CVE-2026-4408_p16.patch \
|
||||
file://CVE-2026-4408_p17.patch \
|
||||
file://CVE-2026-4408_p18.patch \
|
||||
"
|
||||
|
||||
SRC_URI:append:libc-musl = " \
|
||||
|
||||
Reference in New Issue
Block a user