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/