From d905dbddf8d2655e6c91752b750cbe9c15837ee5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Oct 2022 13:29:14 +0200 Subject: [PATCH] CVE-2022-3592 lib: Move subdir_of() to source3/lib/util_path.c Make it available for other components Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207 Signed-off-by: Volker Lendecke --- source3/lib/util_path.c | 50 +++++++++++++++++++++++++++++++++++++++ source3/lib/util_path.h | 4 ++++ source3/smbd/open.c | 52 ----------------------------------------- 3 files changed, 54 insertions(+), 52 deletions(-) diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c index 33827fcf894..5a94b391dd6 100644 --- a/source3/lib/util_path.c +++ b/source3/lib/util_path.c @@ -304,3 +304,53 @@ bool extract_snapshot_token(char *fname, NTTIME *twrp) return true; } + +/* + * Take two absolute paths, figure out if "subdir" is a proper + * subdirectory of "parent". Return the component relative to the + * "parent" without the potential "/". Take care of "parent" + * possibly ending in "/". + */ +bool subdir_of(const char *parent, + size_t parent_len, + const char *subdir, + const char **_relative) +{ + const char *relative = NULL; + bool matched; + + SMB_ASSERT(parent[0] == '/'); + SMB_ASSERT(subdir[0] == '/'); + + if (parent_len == 1) { + /* + * Everything is below "/" + */ + *_relative = subdir+1; + return true; + } + + if (parent[parent_len-1] == '/') { + parent_len -= 1; + } + + matched = (strncmp(subdir, parent, parent_len) == 0); + if (!matched) { + return false; + } + + relative = &subdir[parent_len]; + + if (relative[0] == '\0') { + *_relative = relative; /* nothing left */ + return true; + } + + if (relative[0] == '/') { + /* End of parent must match a '/' in subdir. */ + *_relative = relative+1; + return true; + } + + return false; +} diff --git a/source3/lib/util_path.h b/source3/lib/util_path.h index 33699da28c2..5b0a1f13e38 100644 --- a/source3/lib/util_path.h +++ b/source3/lib/util_path.h @@ -49,5 +49,9 @@ bool clistr_is_previous_version_path(const char *path, const char **startp, const char **endp, NTTIME *ptwrp); +bool subdir_of(const char *parent, + size_t parent_len, + const char *subdir, + const char **_relative); #endif diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d85b0d8ef8..d4a679a4cb0 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -475,58 +475,6 @@ static NTSTATUS check_base_file_access(struct files_struct *fsp, access_mask); } -/* - * Take two absolute paths, figure out if "subdir" is a proper - * subdirectory of "parent". Return the component relative to the - * "parent" without the potential "/". Take care of "parent" - * possibly ending in "/". - */ -static bool subdir_of( - const char *parent, - size_t parent_len, - const char *subdir, - const char **_relative) - -{ - const char *relative = NULL; - bool matched; - - SMB_ASSERT(parent[0] == '/'); - SMB_ASSERT(subdir[0] == '/'); - - if (parent_len == 1) { - /* - * Everything is below "/" - */ - *_relative = subdir+1; - return true; - } - - if (parent[parent_len-1] == '/') { - parent_len -= 1; - } - - matched = (strncmp(subdir, parent, parent_len) == 0); - if (!matched) { - return false; - } - - relative = &subdir[parent_len]; - - if (relative[0] == '\0') { - *_relative = relative; /* nothing left */ - return true; - } - - if (relative[0] == '/') { - /* End of parent must match a '/' in subdir. */ - *_relative = relative+1; - return true; - } - - return false; -} - static NTSTATUS chdir_below_conn( TALLOC_CTX *mem_ctx, connection_struct *conn,