The branch, v4-21-test has been updated via 5ba371e09ab WHATSNEW: update the Per-user and group "veto files" and "hide files" section via bffa9349d42 docs: Document parametric form of hide and veto files via d5be00ab537 lib: Remove "token" parameter from set_namearray via 13dbaf5556c lib: Remove per-user support from append_to_namearray via 244ade4f12c tests: Test parametric per-user syntax for hide/veto files via fd73c865eed smbd: Respect per-user hide and veto files with parametric options via af0085aced4 lib: Factor out append_namearray from set_namearray via 0b9371aa0c2 loadparm: Add lp_wi_scan_share_parametrics via 5148ff97061 loadparm: Factor out lp_wi_scan_parametrics from 13fc70f5e04 VERSION: Bump version up to Samba 4.21.0rc2...
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-21-test - Log ----------------------------------------------------------------- commit 5ba371e09ab284e4ada0e6f3275a07711e7dd069 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jul 31 11:56:35 2024 +0200 WHATSNEW: update the Per-user and group "veto files" and "hide files" section BUG: https://bugzilla.samba.org/show_bug.cgi?id=15688 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Volker Lendecke <v...@samba.org> Autobuild-User(v4-21-test): Stefan Metzmacher <me...@samba.org> Autobuild-Date(v4-21-test): Wed Jul 31 16:07:37 UTC 2024 on atb-devel-224 commit bffa9349d425bcb2b4532ea27194d4a0727b6d31 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 (cherry picked from commit 10e9b858a3f9ca8d7e5dfd1c4e1e7937a03db671) commit d5be00ab537b2e5256926c4753793b4ce561956d 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> (cherry picked from commit a150714cc64294d75028bac47132084bdf6f72c9) commit 13dbaf5556c6a3778d384ed833a896e266546557 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> (cherry picked from commit b5169dd717ed5cf66d1e1e90aaf1a4646f7b5ea5) commit 244ade4f12c0b9f72ffd640cd16a6c1a2c1ce37e 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> (cherry picked from commit b5a128685e68f05a3688aa1391393b9095bf32b0) commit fd73c865eed811d89da023a77792aba7a603fc60 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> (cherry picked from commit 17becb5f526015de56d00cd1c8f603f8ddacd0ba) commit af0085aced4f2a7c8a11bbf357dc25b5ceb0928a 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> (cherry picked from commit fcd595a4642a08169b427af534a00116daf220bf) commit 0b9371aa0c22684bb9d168a67891d92107023736 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> (cherry picked from commit 89da15756d81746d80b43c2fe04c51fc07591849) commit 5148ff97061c1eb10c66c84e4e353daae7a5a17b 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> (cherry picked from commit 0536ac96e927c00121e220f45cd63682726bc8e3) ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 6 +- 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 +- 12 files changed, 287 insertions(+), 101 deletions(-) Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 99f9f0aa7a6..bf2dbb94b3a 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -180,8 +180,10 @@ Per-user and group "veto files" and "hide files" "veto files" and "hide files" can optionally be restricted to certain users and groups. To apply a veto or hide directive to a filename for a specific user or -group, prefix the filename with "../USERNAME/" or "../GROUPNAME/". For details -consult the updated smb.conf manpage. +group, a parametric option like this can be used: + hide files : USERNAME = /somefile.txt/ + veto files : GROUPNAME = /otherfile.txt/ +For details consult the updated smb.conf manpage. Automatic keytab update after machine password change ----------------------------------------------------- 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) { -- Samba Shared Repository