The branch, master has been updated via 8292481bc06 smbd: Don't talloc_zero where we assign the struct a line below via e989d7383ef lib: Remove a few duplicate prototypes via a8405ed15b4 lib: Remove unused strnrchr_w via f31478e782f lib: Remove unused strnrchr_m via f1fae5403ea docs: "share:fake_fscaps" is per share, not global via 94f37866b5b smbd: Use new symlink_target_path routine via b91e257f565 libcli: New routine symlink_target_path for [MS-SMB2] 2.2.2.2.1.1 via 659cb9f7280 smbd: Rename symlink_target_path to _symlink_target_path from 93a3dd48d66 gitlab-ci: Also add the git directory for pipeline in the main mirror
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 8292481bc06f0a6a905e1cd98f24269cf40161b2 Author: Volker Lendecke <v...@samba.org> Date: Thu Jun 27 16:46:16 2024 +0200 smbd: Don't talloc_zero where we assign the struct a line below Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> Autobuild-User(master): Volker Lendecke <v...@samba.org> Autobuild-Date(master): Thu Jul 4 16:31:39 UTC 2024 on atb-devel-224 commit e989d7383ef872e5b8cad41507ae0630d18efe61 Author: Volker Lendecke <v...@samba.org> Date: Thu Jun 27 18:20:05 2024 +0200 lib: Remove a few duplicate prototypes Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit a8405ed15b4d0f073153620c251582eedf771c65 Author: Volker Lendecke <v...@samba.org> Date: Thu Jun 27 17:54:56 2024 +0200 lib: Remove unused strnrchr_w Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit f31478e782ff28619f16be7dd95bf9d0f64f7d10 Author: Volker Lendecke <v...@samba.org> Date: Thu Jun 27 17:54:01 2024 +0200 lib: Remove unused strnrchr_m Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit f1fae5403ea672eca0bc4c1bc641003a9e641695 Author: Volker Lendecke <v...@samba.org> Date: Wed Jul 3 09:58:02 2024 +0200 docs: "share:fake_fscaps" is per share, not global Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 94f37866b5ba74f08509cac376c5d1ed84c9d3e3 Author: Volker Lendecke <v...@samba.org> Date: Thu Jul 4 11:07:54 2024 +0200 smbd: Use new symlink_target_path routine Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit b91e257f565797849d384cce8f8a200755f71700 Author: Volker Lendecke <v...@samba.org> Date: Wed Jul 3 15:55:46 2024 +0200 libcli: New routine symlink_target_path for [MS-SMB2] 2.2.2.2.1.1 Right now the only user is the user-space symlink following in smbd. We will use it in libsmb as well to correctly handle STOPPED_ON_SYMLINK. When trying to upstream that code I found the previous_slash function incredibly hard to understand. This new routine makes copy of "const char *_name_in", so that we can replace previous_slash with a simple strrchr_m. If that's too slow (which I doubt, this is "only" chasing symlinks) we can always do something smarter again. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 659cb9f728036e18834fac5bad99f8ef7ba5230e Author: Volker Lendecke <v...@samba.org> Date: Wed Jul 3 15:38:18 2024 +0200 smbd: Rename symlink_target_path to _symlink_target_path Only temporary, next step is a new more general symlink_target_path routine, we'll need that in libcli/smb as well. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> ----------------------------------------------------------------------- Summary of changes: docs-xml/smbdotconf/protocol/sharefakefscaps.xml | 2 +- lib/util/charset/charset.h | 1 - lib/util/charset/util_unistr_w.c | 26 ------- libcli/smb/reparse.c | 94 ++++++++++++++++++++++++ libcli/smb/reparse.h | 8 ++ source3/include/proto.h | 7 -- source3/lib/util_str.c | 35 --------- source3/smbd/filename.c | 81 +++----------------- source3/smbd/files.c | 2 +- 9 files changed, 114 insertions(+), 142 deletions(-) Changeset truncated at 500 lines: diff --git a/docs-xml/smbdotconf/protocol/sharefakefscaps.xml b/docs-xml/smbdotconf/protocol/sharefakefscaps.xml index 11f495526f5..31e7ebc0e75 100644 --- a/docs-xml/smbdotconf/protocol/sharefakefscaps.xml +++ b/docs-xml/smbdotconf/protocol/sharefakefscaps.xml @@ -1,5 +1,5 @@ <samba:parameter name="share:fake_fscaps" - context="G" + context="S" type="string" xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> <description> diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index 8452b5766d1..4316c1b2c6c 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -292,7 +292,6 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max); smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c); smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c); smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c); -smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n); smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins); bool strlower_w(smb_ucs2_t *s); bool strupper_w(smb_ucs2_t *s); diff --git a/lib/util/charset/util_unistr_w.c b/lib/util/charset/util_unistr_w.c index 88d5531bb71..e49b796bac4 100644 --- a/lib/util/charset/util_unistr_w.c +++ b/lib/util/charset/util_unistr_w.c @@ -114,32 +114,6 @@ smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) return NULL; } -/******************************************************************* - Wide version of strrchr that returns after doing strrchr 'n' times. -********************************************************************/ - -smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n) -{ - smb_ucs2_t cp; - const smb_ucs2_t *p = s; - int len = strlen_w(s); - - if (len == 0 || !n) { - return NULL; - } - p += (len - 1); - do { - if (c == *(COPY_UCS2_CHAR(&cp,p))) { - n--; - } - - if (!n) { - return discard_const_p(smb_ucs2_t, p); - } - } while (p-- != s); - return NULL; -} - /******************************************************************* Wide strstr(). ********************************************************************/ diff --git a/libcli/smb/reparse.c b/libcli/smb/reparse.c index 08071ca85d7..ffadf1c35af 100644 --- a/libcli/smb/reparse.c +++ b/libcli/smb/reparse.c @@ -565,3 +565,97 @@ ssize_t reparse_data_buffer_marshall(const struct reparse_data_buffer *src, return ret; } + +/* + * Implement [MS-SMB2] 2.2.2.2.1.1 Handling the Symbolic Link Error Response + */ + +int symlink_target_path(TALLOC_CTX *ctx, + const char *_name_in, + size_t num_unparsed, + const char *substitute, + bool relative, + char separator, + char **_target) +{ + size_t name_in_len = strlen(_name_in); + size_t num_parsed; + char name_in[name_in_len + 1]; + char *unparsed = NULL; + char *syml = NULL; + char *target = NULL; + + if (num_unparsed > name_in_len) { + return EINVAL; + } + num_parsed = name_in_len - num_unparsed; + + /* + * We need to NULL out separators in name_in. Make a copy of + * _name_in, which is a const char *. + */ + memcpy(name_in, _name_in, sizeof(name_in)); + + unparsed = name_in + num_parsed; + + if ((num_unparsed != 0) && (unparsed[0] != separator)) { + /* + * Symlinks in the middle of name_in must end in a separator + */ + return EINVAL; + } + + if (!relative) { + /* + * From [MS-SMB2] 2.2.2.2.1.1: + * + * If the SYMLINK_FLAG_RELATIVE flag is not set in the Flags + * field of the symbolic link error response, the unparsed + * portion of the file name MUST be appended to the substitute + * name to create the new target path name. + */ + target = talloc_asprintf(ctx, "%s%s", substitute, unparsed); + goto done; + } + + /* + * From [MS-SMB2] 2.2.2.2.1.1: + * + * If the SYMLINK_FLAG_RELATIVE flag is set in the Flags field + * of the symbolic link error response, the symbolic link name + * MUST be identified by backing up one path name element from + * the unparsed portion of the path name. The symbolic link + * MUST be replaced with the substitute name to create the new + * target path name. + */ + + { + char symlink_end_char = unparsed[0]; /* '\0' or a separator */ + + unparsed[0] = '\0'; + syml = strrchr_m(name_in, separator); + unparsed[0] = symlink_end_char; + } + + if (syml == NULL) { + /* + * Nothing to back up to, the symlink was the first + * path component. + */ + name_in[0] = '\0'; + } else { + /* + * Make "name_in" up to the symlink usable for asprintf + */ + syml[1] = '\0'; + } + + target = talloc_asprintf(ctx, "%s%s%s", name_in, substitute, unparsed); + +done: + if (target == NULL) { + return ENOMEM; + } + *_target = target; + return 0; +} diff --git a/libcli/smb/reparse.h b/libcli/smb/reparse.h index e4410d974e4..78c55ca3245 100644 --- a/libcli/smb/reparse.h +++ b/libcli/smb/reparse.h @@ -79,4 +79,12 @@ ssize_t reparse_data_buffer_marshall(const struct reparse_data_buffer *src, uint8_t *buf, size_t buflen); +int symlink_target_path(TALLOC_CTX *ctx, + const char *_name_in, + size_t num_unparsed, + const char *substitute, + bool relative, + char separator, + char **_target); + #endif diff --git a/source3/include/proto.h b/source3/include/proto.h index bd7efce1f39..1db239f0559 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -526,15 +526,8 @@ char *realloc_string_sub(char *string, const char *insert); void all_string_sub(char *s,const char *pattern,const char *insert, size_t len); char *string_truncate(char *s, unsigned int length); -char *strchr_m(const char *src, char c); -char *strrchr_m(const char *s, char c); -char *strnrchr_m(const char *s, char c, unsigned int n); -char *strstr_m(const char *src, const char *findstr); bool strlower_m(char *s); bool strupper_m(char *s); -size_t strlen_m(const char *s); -size_t strlen_m_term(const char *s); -size_t strlen_m_term_null(const char *s); int fstr_sprintf(fstring s, const char *fmt, ...); uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr); diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 1591420587e..7c7872d6809 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -192,41 +192,6 @@ char *string_truncate(char *s, unsigned int length) return s; } - -/*********************************************************************** - Return the equivalent of doing strrchr 'n' times - always going - backwards. -***********************************************************************/ - -char *strnrchr_m(const char *s, char c, unsigned int n) -{ - smb_ucs2_t *ws = NULL; - char *s2 = NULL; - smb_ucs2_t *p; - char *ret; - size_t converted_size; - - if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { - /* Too hard to try and get right. */ - return NULL; - } - p = strnrchr_w(ws, UCS2_CHAR(c), n); - if (!p) { - TALLOC_FREE(ws); - return NULL; - } - *p = 0; - if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { - TALLOC_FREE(ws); - /* Too hard to try and get right. */ - return NULL; - } - ret = discard_const_p(char, (s+strlen(s2))); - TALLOC_FREE(ws); - TALLOC_FREE(s2); - return ret; -} - static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) { size_t size; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 941a4ade5d0..e6bc60ae217 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -594,71 +594,6 @@ static NTSTATUS filename_convert_normalize_new( return NT_STATUS_OK; } -static const char *previous_slash(const char *name_in, const char *slash) -{ - const char *prev = NULL; - - SMB_ASSERT((name_in <= slash) && (slash[0] == '/')); - - prev = strchr_m(name_in, '/'); - - if (prev == slash) { - /* No previous slash */ - return NULL; - } - - while (true) { - const char *next = strchr_m(prev + 1, '/'); - - if (next == slash) { - return prev; - } - prev = next; - } - - return NULL; /* unreachable */ -} - -static char *symlink_target_path( - TALLOC_CTX *mem_ctx, - const char *name_in, - const char *substitute, - size_t unparsed) -{ - size_t name_in_len = strlen(name_in); - const char *p_unparsed = NULL; - const char *parent = NULL; - char *ret; - - SMB_ASSERT(unparsed <= name_in_len); - - p_unparsed = name_in + (name_in_len - unparsed); - - if (substitute[0] == '/') { - ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed); - return ret; - } - - if (unparsed == 0) { - parent = strrchr_m(name_in, '/'); - } else { - parent = previous_slash(name_in, p_unparsed); - } - - if (parent == NULL) { - ret = talloc_asprintf(mem_ctx, "%s%s", substitute, p_unparsed); - } else { - ret = talloc_asprintf(mem_ctx, - "%.*s/%s%s", - (int)(parent - name_in), - name_in, - substitute, - p_unparsed); - } - - return ret; -} - NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx, const char *connectpath, const char *dir, @@ -1139,6 +1074,7 @@ NTSTATUS filename_convert_dirfsp( char *target = NULL; char *safe_target = NULL; size_t symlink_redirects = 0; + int ret; next: if (symlink_redirects > 40) { @@ -1203,12 +1139,15 @@ next: * resolve all symlinks locally. */ - target = symlink_target_path(mem_ctx, - name_in, - lnk->substitute_name, - lnk->unparsed_path_length); - if (target == NULL) { - return NT_STATUS_NO_MEMORY; + ret = symlink_target_path(mem_ctx, + name_in, + lnk->unparsed_path_length, + lnk->substitute_name, + lnk->substitute_name[0] != '/', + '/', + &target); + if (ret != 0) { + return map_nt_error_from_unix(ret); } status = safe_symlink_target_path(mem_ctx, diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 0ab8aa80f20..d7062cd2016 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -742,7 +742,7 @@ NTSTATUS read_symlink_reparse(TALLOC_CTX *mem_ctx, struct symlink_reparse_struct *lnk = NULL; NTSTATUS status; - reparse = talloc_zero(mem_ctx, struct reparse_data_buffer); + reparse = talloc(mem_ctx, struct reparse_data_buffer); if (reparse == NULL) { goto nomem; } -- Samba Shared Repository