From: Stefan Metzmacher Date: Fri, 11 Jun 2021 19:03:42 +0000 (+0000) Subject: s3:lib: add samba_path_matching_regex_sub1_create() X-Git-Tag: tevent-0.11.0~105 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc39450d80b2f319501747d8b285d0d70ca6505b;p=thirdparty%2Fsamba.git s3:lib: add samba_path_matching_regex_sub1_create() This will allow the usage 'POSIX Basic Regular Expression' instead of 'ms wildcard' strings. We allow exactly one 'subexpression' starting with '\(' and ending with '\)' in order to find a replacement (byte) region in the matching string. This will be used in the vfs_preopen module in the following commits. Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/source3/lib/util_matching.c b/source3/lib/util_matching.c index a11ff494c74..4a321f2ca44 100644 --- a/source3/lib/util_matching.c +++ b/source3/lib/util_matching.c @@ -24,6 +24,7 @@ struct samba_path_matching_entry { const char *name; bool is_wild; + regex_t re; }; struct samba_path_matching_result { @@ -211,6 +212,114 @@ NTSTATUS samba_path_matching_mswild_create(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; }; +static int samba_path_matching_regex_sub1_destructor(struct samba_path_matching *pm) +{ + ssize_t i; + + for (i = 0; i < pm->num_entries; i++) { + struct samba_path_matching_entry *e = &pm->entries[i]; + + regfree(&e->re); + } + + pm->num_entries = 0; + + return 0; +} + +static NTSTATUS samba_path_create_regex_sub1_fn(const struct samba_path_matching *pm, + const struct samba_path_matching_entry *e, + const char *namecomponent, + struct samba_path_matching_result *result) +{ + if (e->re.re_nsub == 1) { + regmatch_t matches[2] = { }; + int ret; + + ret = regexec(&e->re, namecomponent, 2, matches, 0); + if (ret == 0) { + *result = (struct samba_path_matching_result) { + .match = true, + .replace_start = matches[1].rm_so, + .replace_end = matches[1].rm_eo, + }; + + return NT_STATUS_OK; + } + } + + *result = (struct samba_path_matching_result) { + .match = false, + .replace_start = -1, + .replace_end = -1, + }; + + return NT_STATUS_OK; +} + +NTSTATUS samba_path_matching_regex_sub1_create(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct samba_path_matching **ppm) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + struct samba_path_matching *pm = NULL; + ssize_t i; + + *ppm = NULL; + + status = samba_path_matching_split(mem_ctx, namelist_in, &pm); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + talloc_reparent(mem_ctx, frame, pm); + + for (i = 0; i < pm->num_entries; i++) { + struct samba_path_matching_entry *e = &pm->entries[i]; + int ret; + + ret = regcomp(&e->re, e->name, 0); + if (ret != 0) { + fstring buf = { 0,}; + + regerror(ret, &e->re, buf, sizeof(buf)); + + DBG_ERR("idx[%zu] regcomp: /%s/ - %d - %s\n", + i, e->name, ret, buf); + + status = NT_STATUS_INVALID_PARAMETER; + i--; + goto cleanup; + } + + if (e->re.re_nsub != 1) { + DBG_ERR("idx[%zu] regcomp: /%s/ - re_nsub[%zu] != 1\n", + i, e->name, e->re.re_nsub); + status = NT_STATUS_INVALID_PARAMETER; + goto cleanup; + } + } + + talloc_set_destructor(pm, samba_path_matching_regex_sub1_destructor); + + pm->case_sensitive = true; + pm->matching_fn = samba_path_create_regex_sub1_fn; + *ppm = talloc_move(mem_ctx, &pm); + TALLOC_FREE(frame); + return NT_STATUS_OK; + +cleanup: + for (; i >= 0; i--) { + struct samba_path_matching_entry *e = &pm->entries[i]; + + regfree(&e->re); + } + + TALLOC_FREE(frame); + return status; +}; + NTSTATUS samba_path_matching_check_last_component(struct samba_path_matching *pm, const char *name, ssize_t *p_match_idx, diff --git a/source3/lib/util_matching.h b/source3/lib/util_matching.h index 71b8600c51b..5abe40e0f06 100644 --- a/source3/lib/util_matching.h +++ b/source3/lib/util_matching.h @@ -27,6 +27,10 @@ NTSTATUS samba_path_matching_mswild_create(TALLOC_CTX *mem_ctx, const char *namelist_in, struct samba_path_matching **ppm); +NTSTATUS samba_path_matching_regex_sub1_create(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct samba_path_matching **ppm); + NTSTATUS samba_path_matching_check_last_component(struct samba_path_matching *pm, const char *name, ssize_t *p_match_idx, diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 606e398ea6e..49ba9b507cb 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -282,6 +282,7 @@ local_tests = [ "LOCAL-MEMCACHE", "LOCAL-STREAM-NAME", "LOCAL-STR-MATCH-MSWILD", + "LOCAL-STR-MATCH-REGEX-SUB1", "LOCAL-string_to_sid", "LOCAL-sid_to_string", "LOCAL-binary_to_sid", diff --git a/source3/torture/proto.h b/source3/torture/proto.h index 5b740e89b6a..90363577ad9 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -102,6 +102,7 @@ bool run_async_echo(int dummy); bool run_smb_any_connect(int dummy); bool run_addrchange(int dummy); bool run_str_match_mswild(int dummy); +bool run_str_match_regex_sub1(int dummy); bool run_notify_online(int dummy); bool run_nttrans_create(int dummy); bool run_nttrans_fsctl(int dummy); diff --git a/source3/torture/test_matching.c b/source3/torture/test_matching.c index f94fa9a3dd0..647b758a34a 100644 --- a/source3/torture/test_matching.c +++ b/source3/torture/test_matching.c @@ -148,3 +148,129 @@ bool run_str_match_mswild(int dummy) return ret; } + +bool run_str_match_regex_sub1(int dummy) +{ + const char *invalidlist1 = "/Re7599Ex[0-9].*\\.txt/"; + const char *invalidlist2 = "/Re7599Ex\\([0-9]\\).*\\.\\(txt\\)/"; + const char *invalidlist3 = "/Re7599Ex\\([0-9]).*\\.txt/"; + const char *invalidlist4 = "/Re7599Ex[0-9.*\\.txt/"; + const char *namelist = "/Re7599Ex\\([0-9]\\).*\\.txt/test\\(.*\\).txt/^test\\([0-9]*\\).dat/"; + struct samba_path_matching *pm = NULL; + const struct str_match_regex_sub1 { + const char *name; + ssize_t match_idx; + ssize_t sub_start; + ssize_t sub_end; + } names[] = {{ + .name = "/dir/Re7599Ex567.txt", + .match_idx = 0, + .sub_start = 13, + .sub_end = 14, + },{ + .name = "/dir/rE7599eX567.txt", + .match_idx = -1, + .sub_start = -1, + .sub_end = -1, + },{ + .name = "/dir/Re7599Ex.txt", + .match_idx = -1, + .sub_start = -1, + .sub_end = -1, + },{ + .name = "/dir/testabc123.txt", + .match_idx = 1, + .sub_start = 9, + .sub_end = 15, + },{ + .name = "/dir/testabc123.tXt", + .match_idx = -1, + .sub_start = -1, + .sub_end = -1, + },{ + .name = "/dir/test123.dat", + .match_idx = 2, + .sub_start = 9, + .sub_end = 12, + },{ + .name = "/dir/tEst123.dat", + .match_idx = -1, + .sub_start = -1, + .sub_end = -1, + }}; + NTSTATUS status; + size_t i; + bool ret = true; + + d_fprintf(stderr, "invalidlist1: %s\n", invalidlist1); + status = samba_path_matching_regex_sub1_create(talloc_tos(), + invalidlist1, + &pm); + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)); + d_fprintf(stderr, "invalidlist2: %s\n", invalidlist2); + status = samba_path_matching_regex_sub1_create(talloc_tos(), + invalidlist2, + &pm); + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)); + d_fprintf(stderr, "invalidlist3: %s\n", invalidlist3); + status = samba_path_matching_regex_sub1_create(talloc_tos(), + invalidlist3, + &pm); + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)); + d_fprintf(stderr, "invalidlist4: %s\n", invalidlist4); + status = samba_path_matching_regex_sub1_create(talloc_tos(), + invalidlist4, + &pm); + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)); + + d_fprintf(stderr, "namelist: %s\n", namelist); + status = samba_path_matching_regex_sub1_create(talloc_tos(), + namelist, + &pm); + SMB_ASSERT(NT_STATUS_IS_OK(status)); + + for (i = 0; i < ARRAY_SIZE(names); i++) { + const struct str_match_regex_sub1 *n = &names[i]; + ssize_t match_idx = -1; + ssize_t replace_start = -1; + ssize_t replace_end = -1; + bool ok = true; + + status = samba_path_matching_check_last_component(pm, + n->name, + &match_idx, + &replace_start, + &replace_end); + SMB_ASSERT(NT_STATUS_IS_OK(status)); + if (match_idx == -1) { + SMB_ASSERT(replace_start == -1); + SMB_ASSERT(replace_end == -1); + } + if (n->match_idx != match_idx) { + ok = false; + } + if (n->sub_start != replace_start) { + ok = false; + } + if (n->sub_end != replace_end) { + ok = false; + } + + d_fprintf(stderr, "name[%s] " + "T[IDX=%zd;START=%zd;END=%zd] " + "M[[IDX=%zd;START=%zd;END=%zd] " + "%s\n", + n->name, + n->match_idx, + n->sub_start, + n->sub_end, + match_idx, + replace_start, + replace_end, + ok ? "OK" : "FAIL"); + + ret &= ok; + } + + return ret; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 05188019982..5deffab6dc2 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -15349,6 +15349,10 @@ static struct { .name = "LOCAL-STR-MATCH-MSWILD", .fn = run_str_match_mswild, }, + { + .name = "LOCAL-STR-MATCH-REGEX-SUB1", + .fn = run_str_match_regex_sub1, + }, { .name = "WBCLIENT-MULTI-PING", .fn = run_wbclient_multi_ping,