[exim-cvs] Lookups: sub-path for dsearch

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] Lookups: sub-path for dsearch
Gitweb: https://git.exim.org/exim.git/commitdiff/48d6f3b6c68a33a4ff11650f9f0de858cb5fc256
Commit:     48d6f3b6c68a33a4ff11650f9f0de858cb5fc256
Parent:     af8a610f0b90ae66f32b7c6ec31381bdd8457b59
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sun May 26 17:17:50 2024 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sun May 26 18:30:45 2024 +0100


    Lookups: sub-path for dsearch
---
 doc/doc-docbook/spec.xfpt      | 16 ++++++++++++++--
 doc/doc-txt/NewStuff           |  2 ++
 src/src/lookups/dsearch.c      | 28 +++++++++++++++++++++-------
 test/scripts/2500-dsearch/2500 |  2 ++
 test/stdout/2500               |  2 ++
 5 files changed, 41 insertions(+), 9 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index 8f7abac89..6ee615145 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -6846,7 +6846,10 @@ by default, but has an option to omit them (see section &<<SECTdbmbuild>>&).
.cindex "dsearch lookup type"
The given file must be an absolute directory path; this is searched for an entry
whose name is the key by calling the &[lstat()]& function.
-The key may not contain any forward slash characters.
+.new
+Unless the options (below) permit a path,
+.wen
+the key may not contain any forward slash characters.
If &[lstat()]& succeeds then so does the lookup.
.cindex "tainted data" "dsearch result"
The result is regarded as untainted.
@@ -6855,7 +6858,7 @@ Options for the lookup can be given by appending them after the word "dsearch",
separated by a comma. Options, if present, are a comma-separated list having
each element starting with a tag name and an equals.

-Two options are supported, for the return value and for filtering match
+Three options are supported, for the return value and for filtering match
candidates.
The "ret" option requests an alternate result value of
the entire path for the entry. Example:
@@ -6863,6 +6866,7 @@ the entire path for the entry. Example:
${lookup {passwd} dsearch,ret=full {/etc}}
.endd
The default result is just the requested entry.
+
The "filter" option requests that only directory entries of a given type
are matched. The match value is one of "file", "dir" or "subdir" (the latter
not matching "." or ".."). Example:
@@ -6872,6 +6876,14 @@ ${lookup {passwd} dsearch,filter=file {/etc}}
The default matching is for any entry type, including directories
and symlinks.

+The "key" option relaxes the restriction that only a simple path component can
+be searched for, to permit a sequence of path components. Example:
+.code
+${lookup {foo/bar} dsearch,key=path {/etc}}
+.endd
+If this option is used, a ".." component in the key is specifically disallowed.
+The default operation is that the key may only be a single path component.
+
An example of how this
lookup can be used to support virtual domains is given in section
&<<SECTvirtualdomains>>&.
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index 1781e05b1..b0702eea2 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -22,6 +22,8 @@ Version 4.98

6. A dns:fail event.

+ 7. The dsearch lookup supports search for a sub-path.
+
Version 4.97
------------

diff --git a/src/src/lookups/dsearch.c b/src/src/lookups/dsearch.c
index 74439bfc8..22003f4e5 100644
--- a/src/src/lookups/dsearch.c
+++ b/src/src/lookups/dsearch.c
@@ -70,6 +70,7 @@ return FALSE;
 #define FILTER_FILE    BIT(2)
 #define FILTER_DIR    BIT(3)
 #define FILTER_SUBDIR    BIT(4)
+#define ALLOW_PATH    BIT(5)


/* See local README for interface description. We use lstat() instead of
scanning the directory, as it is hopefully faster to let the OS do the scanning
@@ -85,13 +86,6 @@ int save_errno;
uschar * filename;
unsigned flags = 0;

-if (Ustrchr(keystring, '/') != 0)
-  {
-  *errmsg = string_sprintf("key for dsearch lookup contains a slash: %s",
-    keystring);
-  return DEFER;
-  }
-
 if (opts)
   {
   int sep = ',';
@@ -110,6 +104,24 @@ if (opts)
       else if (Ustrcmp(ele, "subdir") == 0)
     flags |= FILTER_TYPE | FILTER_SUBDIR;    /* like dir but not "." or ".." */
       }
+    else if (Ustrcmp(ele, "key=path") == 0)
+      flags |= ALLOW_PATH;
+  }
+
+if (flags & ALLOW_PATH)
+  {
+  if (Ustrstr(keystring, "/../") != NULL || Ustrstr(keystring, "/./"))
+    {
+    *errmsg = string_sprintf(
+      "key for dsearch lookup contains bad component: %s", keystring);
+    return DEFER;
+    }
+  }
+else if (Ustrchr(keystring, '/') != NULL)
+  {
+  *errmsg = string_sprintf("key for dsearch lookup contains a slash: %s",
+    keystring);
+  return DEFER;
   }


filename = string_sprintf("%s/%s", dirname, keystring);
@@ -189,3 +201,5 @@ static lookup_info *_lookup_list[] = { &_lookup_info };
lookup_module_info dsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };

 /* End of lookups/dsearch.c */
+/* vi: aw ai sw=2
+*/
diff --git a/test/scripts/2500-dsearch/2500 b/test/scripts/2500-dsearch/2500
index f3937ec91..1690256da 100644
--- a/test/scripts/2500-dsearch/2500
+++ b/test/scripts/2500-dsearch/2500
@@ -18,6 +18,8 @@ ok,subdir:  ${lookup{TESTNUM.dir} dsearch,filter=subdir {DIR/aux-fixed}{$value}{
 fail,subdir(..):${lookup{..}          dsearch,filter=subdir {DIR/aux-fixed}{$value}{FAIL}}
 fail,subdir(.) :${lookup{.}           dsearch,filter=subdir {DIR/aux-fixed}{$value}{FAIL}}
 fail,subdir(f) :${lookup{TESTNUM.tst} dsearch,filter=subdir {DIR/aux-fixed}{$value}{FAIL}}
+fail.path:  ${lookup{TESTNUM.dir/regfile} dsearch          {DIR/aux-fixed}{$value}{FAIL}}
+ok.path:    ${lookup{TESTNUM.dir/regfile} dsearch,key=path {DIR/aux-fixed}{$value}{FAIL}}


 cachelayer tests
 fail:       ${lookup{test-data}   dsearch               {DIR/}          {$value}{FAIL}}
diff --git a/test/stdout/2500 b/test/stdout/2500
index 6daaab658..065004bf2 100644
--- a/test/stdout/2500
+++ b/test/stdout/2500
@@ -15,6 +15,8 @@

> fail,subdir(..):FAIL
> fail,subdir(.) :FAIL
> fail,subdir(f) :FAIL

+> Failed: lookup of "2500.dir/regfile" gave DEFER: key for dsearch lookup contains a slash: 2500.dir/regfile
+> ok.path:    2500.dir/regfile

>
 > cachelayer tests
 > fail:       FAIL


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/