.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.
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:
${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:
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>>&.
6. A dns:fail event.
+ 7. The dsearch lookup supports search for a sub-path.
+
Version 4.97
------------
#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
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 = ',';
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);
lookup_module_info dsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
/* End of lookups/dsearch.c */
+/* vi: aw ai sw=2
+*/
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}}
> 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