X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/67a57a5afd313490a8763d60ec4df857b9cf239b..0006e6d8e151bb4b34452da30da60184736bb5ae:/src/src/search.c diff --git a/src/src/search.c b/src/src/search.c index 51bbc6aed..94a58897f 100644 --- a/src/src/search.c +++ b/src/src/search.c @@ -3,6 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2015 */ +/* Copyright (c) The Exim Maintainers 2020 */ /* See the file NOTICE for conditions of use and distribution. */ /* A set of functions to search databases in various formats. An open @@ -172,20 +173,6 @@ if (Ustrncmp(name, "partial", 7) == 0) /* Now we are left with a lookup name, possibly followed by * or *@, and then by options starting with a "," */ -#ifdef old -len = Ustrlen(ss); -if (len >= 2 && Ustrncmp(ss + len - 2, "*@", 2) == 0) - { - *starflags |= SEARCH_STARAT; - len -= 2; - } -else if (len >= 1 && ss[len-1] == '*') - { - *starflags |= SEARCH_STAR; - len--; - } -#endif - len = Ustrlen(ss); if ((t = Ustrchr(ss, '*'))) { @@ -195,7 +182,14 @@ if ((t = Ustrchr(ss, '*'))) else t = ss; -* USS opts = (t = Ustrchr(t, ',')) ? string_copy(t+1) : NULL; +if ((t = Ustrchr(t, ','))) + { + int l = t - ss; + if (l < len) len = l; + *opts = string_copy(t+1); + } +else + *opts = NULL; /* Check for the individual search type. Only those that are actually in the binary are valid. For query-style types, "partial" and default types are @@ -246,12 +240,10 @@ Returns: nothing static void tidyup_subtree(tree_node *t) { -search_cache *c = (search_cache *)(t->data.ptr); -if (t->left != NULL) tidyup_subtree(t->left); -if (t->right != NULL) tidyup_subtree(t->right); -if (c != NULL && - c->handle != NULL && - lookup_list[c->search_type]->close != NULL) +search_cache * c = (search_cache *)(t->data.ptr); +if (t->left) tidyup_subtree(t->left); +if (t->right) tidyup_subtree(t->right); +if (c && c->handle && lookup_list[c->search_type]->close) lookup_list[c->search_type]->close(c->handle); } @@ -513,6 +505,7 @@ file. No need to check c->item_cache for NULL, tree_search will do so. */ if ( (t = tree_search(c->item_cache, keystring)) && (!(e = t->data.ptr)->expiry || e->expiry > time(NULL)) + && (!opts && !e->opts || opts && e->opts && Ustrcmp(opts, e->opts) == 0) ) { /* Data was in the cache already; set the pointer from the tree node */ data = e->data.ptr; @@ -527,7 +520,9 @@ else DEBUG(D_lookup) { - if (t) debug_printf_indent("cached data found but past valid time; "); + if (t) + debug_printf_indent("cached data found but %s; ", + e->expiry && e->expiry <= time(NULL) ? "out-of-date" : "wrong opts"); debug_printf_indent("%s lookup required for %s%s%s\n", filename ? US"file" : US"database", keystring, @@ -550,23 +545,20 @@ else else if (do_cache) { - int len = keylength + 1; - - if (t) /* Previous, out-of-date cache entry. Update with the */ - { /* new result and forget the old one */ - e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; - e->data.ptr = data; - } - else + if (!t) /* No existing entry. Create new one. */ { + int len = keylength + 1; e = store_get(sizeof(expiring_data) + sizeof(tree_node) + len, is_tainted(keystring)); - e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; - e->data.ptr = data; t = (tree_node *)(e+1); memcpy(t->name, keystring, len); t->data.ptr = e; tree_insertnode(&c->item_cache, t); } + /* Else previous, out-of-date cache entry. Update with the */ + /* new result and forget the old one */ + e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; + e->opts = opts ? string_copy(opts) : NULL; + e->data.ptr = data; } /* If caching was disabled, empty the cache tree. We just set the cache @@ -575,7 +567,7 @@ else else { DEBUG(D_lookup) debug_printf_indent("lookup forced cache cleanup\n"); - c->item_cache = NULL; + c->item_cache = NULL; /* forget all lookups on this connection */ } } @@ -723,7 +715,7 @@ else if (partial >= 0) /* The key in its entirety did not match a wild entry; try chopping off leading components. */ - if (yield == NULL) + if (!yield) { int dotcount = 0; uschar *keystring3 = keystring2 + affixlen; @@ -847,6 +839,19 @@ if (set_null_wild && expand_setup && *expand_setup >= 0) expand_nlength[*expand_setup] = Ustrlen(keystring); } +/* If we have a result, check the options to see if the key was wanted rather +than the result. Return a de-tainted version of the key on the grounds that +it have been validated by the lookup. */ + +if (yield && opts) + { + int sep = ','; + uschar * ele; + while ((ele = string_nextinlist(&opts, &sep, NULL, 0))) + if (Ustrcmp(ele, "ret=key") == 0) + { yield = string_copy_taint(keystring, FALSE); break; } + } + return yield; }