]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:lib: add samba_path_matching_regex_sub1_create()
authorStefan Metzmacher <metze@samba.org>
Fri, 11 Jun 2021 19:03:42 +0000 (19:03 +0000)
committerStefan Metzmacher <metze@samba.org>
Thu, 1 Jul 2021 13:02:31 +0000 (13:02 +0000)
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 <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/lib/util_matching.c
source3/lib/util_matching.h
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_matching.c
source3/torture/torture.c

index a11ff494c7417196eefabfaeae22c1fdc8c8a22f..4a321f2ca441acc2c737bd176018995152833d69 100644 (file)
@@ -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,
index 71b8600c51be79c2845c69d2074e41d9a0f8d16f..5abe40e0f061054687cbcf69c6e8ae06cfd866cc 100644 (file)
@@ -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,
index 606e398ea6e760f21a0ae77e44baadecabe2af5b..49ba9b507cbcdde1e1b687a9260eec373bd4d2fb 100755 (executable)
@@ -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",
index 5b740e89b6ac96c4d9cc34982e615c1715459d78..90363577ad9344263461b0ade58c0f032ed70ed2 100644 (file)
@@ -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);
index f94fa9a3dd0eac76f4ea113ae9704860ebc43691..647b758a34af83e66ed1f49a949bb3bfa2c3364e 100644 (file)
@@ -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;
+}
index 051880199821b60e68c30fb889160a695c56022e..5deffab6dc21e7af312da5b5e202df32125a3755 100644 (file)
@@ -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,