The branch, master has been updated via 10e9b858a3f docs: Document parametric form of hide and veto files via a150714cc64 lib: Remove "token" parameter from set_namearray via b5169dd717e lib: Remove per-user support from append_to_namearray via b5a128685e6 tests: Test parametric per-user syntax for hide/veto files via 17becb5f526 smbd: Respect per-user hide and veto files with parametric options via fcd595a4642 lib: Factor out append_namearray from set_namearray via 89da15756d8 loadparm: Add lp_wi_scan_share_parametrics via 0536ac96e92 loadparm: Factor out lp_wi_scan_parametrics from 7dc19dd94cb s4:torture/smb2: add 'smb2.bench.session-setup'
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 10e9b858a3f9ca8d7e5dfd1c4e1e7937a03db671 Author: Volker Lendecke <v...@samba.org> Date: Tue Jul 30 14:06:21 2024 +0200 docs: Document parametric form of hide and veto files Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Wed Jul 31 09:41:54 UTC 2024 on atb-devel-224 commit a150714cc64294d75028bac47132084bdf6f72c9 Author: Volker Lendecke <v...@samba.org> Date: Tue Jul 30 13:55:57 2024 +0200 lib: Remove "token" parameter from set_namearray Not needed anymore Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit b5169dd717ed5cf66d1e1e90aaf1a4646f7b5ea5 Author: Volker Lendecke <v...@samba.org> Date: Tue Jul 30 13:30:21 2024 +0200 lib: Remove per-user support from append_to_namearray This is done in check_user_ok now Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit b5a128685e68f05a3688aa1391393b9095bf32b0 Author: Volker Lendecke <v...@samba.org> Date: Tue Jul 30 14:11:53 2024 +0200 tests: Test parametric per-user syntax for hide/veto files Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 17becb5f526015de56d00cd1c8f603f8ddacd0ba Author: Volker Lendecke <v...@samba.org> Date: Mon Jul 29 17:49:49 2024 +0200 smbd: Respect per-user hide and veto files with parametric options For my taste this is a nicer configuration syntax than /../username1/file1/../username2/file2/ Is this too expensive? I don't think so. The scanning only happens an tcon time, and it only walks the parametric options. If this turns out to be a performance problem, we should think about smarter data structures for parametric options instead of just a linked list of string triples for everything. Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit fcd595a4642a08169b427af534a00116daf220bf Author: Volker Lendecke <v...@samba.org> Date: Tue Jul 30 13:07:22 2024 +0200 lib: Factor out append_namearray from set_namearray We'll have to add to an existing namearray soon. This turns one talloc_array() into a set of reallocs. This is slower, but set_namearray is only used for smb.conf entries where we don't expect hundreds or more entries to add. I've done this to avoid array length calculations, but if it turns out to be too slow we can get smarter again. Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 89da15756d81746d80b43c2fe04c51fc07591849 Author: Volker Lendecke <v...@samba.org> Date: Mon Jul 29 07:17:21 2024 -0700 loadparm: Add lp_wi_scan_share_parametrics Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 0536ac96e927c00121e220f45cd63682726bc8e3 Author: Volker Lendecke <v...@samba.org> Date: Mon Jul 29 06:27:51 2024 -0700 loadparm: Factor out lp_wi_scan_parametrics We'll scan share parametrics soon as well. Bug: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: docs-xml/smbdotconf/filename/hidefiles.xml | 29 +++++-- docs-xml/smbdotconf/filename/vetofiles.xml | 29 +++++-- selftest/target/Samba3.pm | 6 +- source3/include/proto.h | 4 +- source3/lib/util_namearray.c | 119 ++++++++++++-------------- source3/modules/vfs_virusfilter.c | 2 - source3/param/loadparm.c | 50 +++++++++-- source3/param/loadparm.h | 7 ++ source3/smbd/smb2_service.c | 2 - source3/smbd/uid.c | 132 ++++++++++++++++++++++++++++- source3/torture/test_matching.c | 2 +- 11 files changed, 283 insertions(+), 99 deletions(-) Changeset truncated at 500 lines: diff --git a/docs-xml/smbdotconf/filename/hidefiles.xml b/docs-xml/smbdotconf/filename/hidefiles.xml index f93885e43a3..3290f8df8db 100644 --- a/docs-xml/smbdotconf/filename/hidefiles.xml +++ b/docs-xml/smbdotconf/filename/hidefiles.xml @@ -14,14 +14,22 @@ as in DOS wildcards.</para> <para> - If a file or directory name is prefixed by "../USERNAME/" - or "../GROUPNAME/", then the subsequent filename is only hidden for the - given user or group. Instead of specifying users or groups by name, they - can also be specified by SID. + <smbconfoption name="hide files"/> can also be used as a + parametric option where NAME in</para> + + <para> + hide files : NAME = </para> - <para>User and group names use the same format as <smbconfoption - name="valid users"/>.</para> + <para> + specifies a user or group name with the same syntax as + <smbconfoption name="valid users"/>. This parametric form can + be specified multiple times for different users or + groups. This means that "hide files : NAME" set both + in the [global] and the share section add up, whereas normally + options set in a share section overwrite the default in the + [global] section. + </para> <para>Each entry must be a Unix path, not a DOS path and must not include the Unix directory separator '/'.</para> @@ -46,9 +54,12 @@ hide files = /.*/DesktopFolderDB/TrashFor%m/resource.frk/ ; Hide some files for anyone and some files for specific users and groups -hide files = hideforall1/../joe/hideforuserjoe/hideforall2/../students/hideforstudents/hideforall3 -hide files = ../UNIVERSITY\Alumnis/somefile.txt/../j...@university.org/anotherfile.txt -hide files = ../S-1-5-21-123-456-789-1000/secretfile.txt +hide files = /hideforall1/ +hide files : USER = /hidetoforuser/ +hide files : GROUP = /hideforgroup/ +hide files : UNIVERSITY\Alumnis = /somefile.txt/ +hide files : j...@university.org = /anotherfile.txt/ +hide files : S-1-5-21-123-456-789-1000 = /secretfile.txt/ </programlisting> </para> diff --git a/docs-xml/smbdotconf/filename/vetofiles.xml b/docs-xml/smbdotconf/filename/vetofiles.xml index e47490ee49d..e90cf707c2d 100644 --- a/docs-xml/smbdotconf/filename/vetofiles.xml +++ b/docs-xml/smbdotconf/filename/vetofiles.xml @@ -11,14 +11,22 @@ </para> <para> - If a file or directory name is prefixed by "../USERNAME/" - or "../GROUPNAME/", then the subsequent filename is only hidden for the - given user or group. Instead of specifying users or groups by name, they - can also be specified by SID. + <smbconfoption name="veto files"/> can also be used as a + parametric option where NAME in</para> + + <para> + veto files : NAME = </para> - <para>User and group names use the same format as <smbconfoption - name="valid users"/>.</para> + <para> + specifies a user or group name with the same syntax as + <smbconfoption name="valid users"/>. This parametric form can + be specified multiple times for different users or + groups. This means that "veto files : NAME" set both + in the [global] and the share section add up, whereas normally + options set in a share section overwrite the default in the + [global] section. + </para> <para> Each filename must be a unix path, not a DOS path and must @@ -51,9 +59,12 @@ veto files = /*Security*/*.tmp/*root*/ ; Veto some files for anyone and some files for specific users and groups -veto files = /vetoforall1/../USER/vetoforuser/vetoforall2/../GROUP/vetoforgroup/vetoforall3/ -veto files = ../UNIVERSITY\Alumnis/somefile.txt/../j...@university.org/anotherfile.txt -veto files = ../S-1-5-21-123-456-789-1000/secretfile.txt +veto files = /vetoforall1/ +veto files : USER = /vetotoforuser/ +veto files : GROUP = /vetoforgroup/ +veto files : UNIVERSITY\Alumnis = /somefile.txt/ +veto files : j...@university.org = /anotherfile.txt/ +veto files : S-1-5-21-123-456-789-1000 = /secretfile.txt/ ; Veto the Apple specific files that a NetAtalk server ; creates. diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 8d7f690ecf6..aea64bf5d5d 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1968,6 +1968,8 @@ sub setup_fileserver get quota command = $prefix_abs/getset_quota.py set quota command = $prefix_abs/getset_quota.py + veto files : user1 = /user1file/ + veto files : +group1 = /group1file/ [tarmode] path = $tarmode_sharedir comment = tar test share @@ -2079,7 +2081,9 @@ sub setup_fileserver [veto_files] path = $veto_sharedir - veto files = /veto_name*/../user1/user1file/../user2/user2file/../+group1/group1file/../+group2/group2file + veto files = /veto_name*/ + veto files : user2 = /user2file/ + veto files : +group2 = /group2file/ [delete_yes_unwrite] read only = no diff --git a/source3/include/proto.h b/source3/include/proto.h index 966d038cc40..f398106e5a2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -326,9 +326,11 @@ bool token_contains_name(TALLOC_CTX *mem_ctx, const struct security_token *token, const char *name, bool *match); +bool append_to_namearray(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct name_compare_entry **_name_array); bool set_namearray(TALLOC_CTX *mem_ctx, const char *namelist, - const struct security_token *token, struct name_compare_entry **_name_array); bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type); bool fcntl_getlock(int fd, int op, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid); diff --git a/source3/lib/util_namearray.c b/source3/lib/util_namearray.c index ca3344e09f1..1c5b4ac6a0e 100644 --- a/source3/lib/util_namearray.c +++ b/source3/lib/util_namearray.c @@ -179,6 +179,17 @@ bool token_contains_name(TALLOC_CTX *mem_ctx, return true; } +static size_t namearray_len(const struct name_compare_entry *array) +{ + size_t i = 0; + + while (array[i].name != NULL) { + i += 1; + } + + return i; +} + /******************************************************************* Strip a '/' separated list into an array of name_compare_enties structures suitable for @@ -190,94 +201,70 @@ bool token_contains_name(TALLOC_CTX *mem_ctx, if possible. ********************************************************************/ -bool set_namearray(TALLOC_CTX *mem_ctx, - const char *namelist_in, - const struct security_token *token, - struct name_compare_entry **_name_array) +bool append_to_namearray(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct name_compare_entry **_name_array) { - struct name_compare_entry *name_array = NULL; - struct name_compare_entry *e = NULL; + struct name_compare_entry *name_array = *_name_array; + size_t len; char *namelist = NULL; const char *p = NULL; - size_t num_entries; - bool ok; - - *_name_array = NULL; if ((namelist_in == NULL) || (namelist_in[0] == '\0')) { return true; } - namelist = path_to_strv(mem_ctx, namelist_in); - if (namelist == NULL) { - DBG_ERR("path_to_strv failed\n"); - return false; + if (name_array == NULL) { + name_array = talloc_zero(mem_ctx, struct name_compare_entry); + if (name_array == NULL) { + return false; + } } + len = namearray_len(name_array); - num_entries = strv_count(namelist); - - name_array = talloc_zero_array(mem_ctx, - struct name_compare_entry, - num_entries + 1); - if (name_array == NULL) { - DBG_ERR("talloc failed\n"); - TALLOC_FREE(namelist); + namelist = path_to_strv(name_array, namelist_in); + if (namelist == NULL) { + DBG_ERR("path_to_strv failed\n"); return false; } - namelist = talloc_reparent(mem_ctx, name_array, namelist); - - e = &name_array[0]; - while ((p = strv_next(namelist, p)) != NULL) { + struct name_compare_entry *tmp = NULL; + if (*p == '\0') { /* cope with multiple (useless) /s) */ continue; } - if (ISDOTDOT(p) && token != NULL) { - const char *username = NULL; - bool match; - - /* Get the username */ - p = strv_next(namelist, p); - if (p == NULL) { - DBG_ERR("Missing username\n"); - TALLOC_FREE(namelist); - return false; - } - username = p; - - /* Get the filename */ - p = strv_next(namelist, p); - if (p == NULL) { - DBG_ERR("Missing filename after username '%s'\n", - username); - TALLOC_FREE(namelist); - return false; - } - - ok = token_contains_name(talloc_tos(), - NULL, - NULL, - NULL, - token, - username, - &match); - if (!ok) { - TALLOC_FREE(namelist); - return false; - } - if (!match) { - continue; - } + tmp = talloc_realloc(mem_ctx, + name_array, + struct name_compare_entry, + len + 2); + if (tmp == NULL) { + return false; } - - e->name = p; - e->is_wild = ms_has_wild(e->name); - e++; + name_array = tmp; + + name_array[len] = (struct name_compare_entry){ + .name = p, + .is_wild = ms_has_wild(p), + }; + name_array[len + 1] = (struct name_compare_entry){}; + len += 1; } *_name_array = name_array; return true; } + +bool set_namearray(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct name_compare_entry **_name_array) +{ + bool ret; + + *_name_array = NULL; + + ret = append_to_namearray(mem_ctx, namelist_in, _name_array); + return ret; +} diff --git a/source3/modules/vfs_virusfilter.c b/source3/modules/vfs_virusfilter.c index 6d4a6fdb98c..b566b628ed2 100644 --- a/source3/modules/vfs_virusfilter.c +++ b/source3/modules/vfs_virusfilter.c @@ -258,7 +258,6 @@ static int virusfilter_vfs_connect( if (exclude_files != NULL) { ok = set_namearray(config, exclude_files, - NULL, &config->exclude_files); if (!ok) { DBG_ERR("set_namearray failed\n"); @@ -271,7 +270,6 @@ static int virusfilter_vfs_connect( if (infected_files != NULL) { ok = set_namearray(config, infected_files, - NULL, &config->infected_files); if (!ok) { DBG_ERR("set_namearray failed\n"); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 663edb2c653..f9bc1c42796 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1204,11 +1204,13 @@ static void discard_whitespace(char *str) * See "man regexec" for possible errors */ -int lp_wi_scan_global_parametrics( - const char *regex_str, size_t max_matches, - bool (*cb)(const char *string, regmatch_t matches[], - void *private_data), - void *private_data) +static int lp_wi_scan_parametrics(struct parmlist_entry *parmlist, + const char *regex_str, + size_t max_matches, + bool (*cb)(const char *string, + regmatch_t matches[], + void *private_data), + void *private_data) { struct parmlist_entry *data; regex_t regex; @@ -1219,7 +1221,7 @@ int lp_wi_scan_global_parametrics( return ret; } - for (data = Globals.param_opt; data != NULL; data = data->next) { + for (data = parmlist; data != NULL; data = data->next) { size_t keylen = strlen(data->key); char key[keylen+1]; regmatch_t matches[max_matches]; @@ -1248,6 +1250,42 @@ fail: return ret; } +int lp_wi_scan_global_parametrics(const char *regex_str, + size_t max_matches, + bool (*cb)(const char *string, + regmatch_t matches[], + void *private_data), + void *private_data) +{ + int ret = lp_wi_scan_parametrics( + Globals.param_opt, regex_str, max_matches, cb, private_data); + return ret; +} + +int lp_wi_scan_share_parametrics(int snum, + const char *regex_str, + size_t max_matches, + bool (*cb)(const char *string, + regmatch_t matches[], + void *private_data), + void *private_data) +{ + struct loadparm_service *s = NULL; + int ret; + + if (!LP_SNUM_OK(snum)) { + /* + * We return regex return values here, REG_NOMATCH is + * the closest I could find. + */ + return REG_NOMATCH; + } + s = ServicePtrs[snum]; + + ret = lp_wi_scan_parametrics( + s->param_opt, regex_str, max_matches, cb, private_data); + return ret; +} #define MISSING_PARAMETER(name) \ DEBUG(0, ("%s(): value is NULL or empty!\n", #name)) diff --git a/source3/param/loadparm.h b/source3/param/loadparm.h index 622e2290d3c..e8f06ddbc2c 100644 --- a/source3/param/loadparm.h +++ b/source3/param/loadparm.h @@ -75,6 +75,13 @@ int lp_wi_scan_global_parametrics( bool (*cb)(const char *string, regmatch_t matches[], void *private_data), void *private_data); +int lp_wi_scan_share_parametrics(int snum, + const char *regex_str, + size_t max_matches, + bool (*cb)(const char *string, + regmatch_t matches[], + void *private_data), + void *private_data); const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def); struct loadparm_service; diff --git a/source3/smbd/smb2_service.c b/source3/smbd/smb2_service.c index 06c20c16749..b6e8ca54e85 100644 --- a/source3/smbd/smb2_service.c +++ b/source3/smbd/smb2_service.c @@ -755,7 +755,6 @@ NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, if (!IS_IPC(conn) && !IS_PRINT(conn)) { ok = set_namearray(conn, lp_veto_oplock_files(talloc_tos(), lp_sub, snum), - NULL, &conn->veto_oplock_list); if (!ok) { status = NT_STATUS_NO_MEMORY; @@ -763,7 +762,6 @@ NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn, } ok = set_namearray(conn, lp_aio_write_behind(talloc_tos(), lp_sub, snum), - NULL, &conn->aio_write_behind_list); if (!ok) { status = NT_STATUS_NO_MEMORY; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index fa5f9bcc2f6..2f390651a0e 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -179,6 +179,81 @@ NTSTATUS check_user_share_access(connection_struct *conn, return NT_STATUS_OK; } +struct scan_file_list_state { + TALLOC_CTX *mem_ctx; + const struct loadparm_substitution *lp_sub; + int snum; + const char *param_type; + struct security_token *token; + struct name_compare_entry **list; + bool ok; +}; + +static bool scan_file_list_cb(const char *string, + regmatch_t matches[], + void *private_data) +{ + struct scan_file_list_state *state = private_data; + + if (matches[1].rm_so == -1) { + DBG_WARNING("Found match, but no name??\n"); + goto fail; + } + if (matches[1].rm_eo <= matches[1].rm_so) { + DBG_WARNING("Invalid match\n"); + goto fail; + } + + { + regoff_t len = matches[1].rm_eo - matches[1].rm_so; + char name[len + 1]; + bool ok, match; + char *files = NULL; + + memcpy(name, string + matches[1].rm_so, len); + name[len] = '\0'; + + DBG_DEBUG("Found name \"%s : %s\"\n", state->param_type, name); + + ok = token_contains_name(talloc_tos(), + NULL, + NULL, + NULL, + state->token, + name, + &match); + if (!ok) { + goto fail; + } + if (!match) { + return false; /* don't stop traverse */ + } + + files = lp_parm_substituted_string(state->mem_ctx, + state->lp_sub, + state->snum, + state->param_type, + name, + NULL); + if (files == NULL) { + goto fail; + } + + ok = append_to_namearray(state->mem_ctx, -- Samba Shared Repository