Commit | Line | Data |
---|---|---|
059ec3d9 PH |
1 | /************************************************* |
2 | * Exim - an Internet mail transport agent * | |
3 | *************************************************/ | |
4 | ||
3386088d | 5 | /* Copyright (c) University of Cambridge 1995 - 2015 */ |
1e1ddfac | 6 | /* Copyright (c) The Exim Maintainers 2020 */ |
059ec3d9 PH |
7 | /* See the file NOTICE for conditions of use and distribution. */ |
8 | ||
9 | /* A set of functions to search databases in various formats. An open | |
10 | database is represented by a void * value which is returned from a lookup- | |
11 | specific "open" function. These are now all held in individual modules in the | |
12 | lookups subdirectory and the functions here form a generic interface. | |
13 | ||
14 | Caching is used to improve performance. Open files are cached until a tidyup | |
15 | function is called, and for each file the result of the last lookup is cached. | |
16 | However, if too many files are opened, some of those that are not in use have | |
17 | to be closed. Those open items that use real files are kept on a LRU chain to | |
18 | help with this. | |
19 | ||
20 | All the data is held in permanent store so as to be independent of the stacking | |
21 | pool that is reset from time to time. In fact, we use malloc'd store so that it | |
22 | can be freed when the caches are tidied up. It isn't actually clear whether | |
23 | this is a benefit or not, to be honest. */ | |
24 | ||
25 | #include "exim.h" | |
26 | ||
27 | ||
28 | /* Tree in which to cache open files until tidyup called. */ | |
29 | ||
30 | static tree_node *search_tree = NULL; | |
31 | ||
32 | /* Two-way chain of open databases that use real files. This is maintained in | |
33 | recently-used order for the purposes of closing the least recently used when | |
34 | too many files are open. */ | |
35 | ||
36 | static tree_node *open_top = NULL; | |
37 | static tree_node *open_bot = NULL; | |
38 | ||
39 | /* Count of open databases that use real files */ | |
40 | ||
41 | static int open_filecount = 0; | |
42 | ||
43 | /* Allow us to reset store used for lookups and lookup caching */ | |
44 | ||
f3ebb786 | 45 | static rmark search_reset_point = NULL; |
059ec3d9 PH |
46 | |
47 | ||
48 | ||
49 | /************************************************* | |
50 | * Validate a plain lookup type name * | |
51 | *************************************************/ | |
52 | ||
53 | /* Only those names that are recognized and whose code is included in the | |
54 | binary give an OK response. Use a binary chop search now that the list has got | |
55 | so long. | |
56 | ||
57 | Arguments: | |
58 | name lookup type name - not necessarily zero terminated (e.g. dbm*) | |
59 | len length of the name | |
60 | ||
61 | Returns: +ve => valid lookup name; value is offset in lookup_list | |
62 | -ve => invalid name; message in search_error_message. | |
63 | */ | |
64 | ||
65 | int | |
55414b25 | 66 | search_findtype(const uschar *name, int len) |
059ec3d9 PH |
67 | { |
68 | int bot = 0; | |
69 | int top = lookup_list_count; | |
70 | while (top > bot) | |
71 | { | |
72 | int mid = (top + bot)/2; | |
e6d225ae | 73 | int c = Ustrncmp(name, lookup_list[mid]->name, len); |
059ec3d9 PH |
74 | |
75 | /* If c == 0 we have matched the incoming name with the start of the search | |
76 | type name. However, some search types are substrings of others (e.g. nis and | |
77 | nisplus) so we need to check that the lengths are the same. The length of the | |
78 | type name cannot be shorter (else c would not be 0); if it is not equal it | |
79 | must be longer, and in that case, the incoming name comes before the name we | |
80 | are testing. By leaving c == 0 when the lengths are different, and doing a | |
81 | > 0 test below, this all falls out correctly. */ | |
82 | ||
e6d225ae | 83 | if (c == 0 && Ustrlen(lookup_list[mid]->name) == len) |
059ec3d9 | 84 | { |
e6d225ae | 85 | if (lookup_list[mid]->find != NULL) return mid; |
059ec3d9 PH |
86 | search_error_message = string_sprintf("lookup type \"%.*s\" is not " |
87 | "available (not in the binary - check buildtime LOOKUP configuration)", | |
88 | len, name); | |
89 | return -1; | |
90 | } | |
91 | ||
92 | if (c > 0) bot = mid + 1; else top = mid; | |
93 | } | |
94 | ||
95 | search_error_message = string_sprintf("unknown lookup type \"%.*s\"",len,name); | |
96 | return -1; | |
97 | } | |
98 | ||
99 | ||
100 | ||
101 | /************************************************* | |
102 | * Validate a full lookup type name * | |
103 | *************************************************/ | |
104 | ||
105 | /* This function recognizes the "partial-" prefix and also terminating * and *@ | |
106 | suffixes. | |
107 | ||
108 | Arguments: | |
109 | name the full lookup type name | |
110 | ptypeptr where to put the partial type | |
111 | after subtraction of 1024 or 2048: | |
112 | negative => no partial matching | |
113 | non-negative => minimum number of non-wild components | |
114 | ptypeaff where to put a pointer to the affix | |
115 | the affix is within name if supplied therein | |
116 | otherwise it's a literal string | |
117 | afflen the length of the affix | |
118 | starflags where to put the SEARCH_STAR and SEARCH_STARAT flags | |
67a57a5a | 119 | opts where to put the options |
059ec3d9 PH |
120 | |
121 | Returns: +ve => valid lookup name; value is offset in lookup_list | |
122 | -ve => invalid name; message in search_error_message. | |
123 | */ | |
124 | ||
125 | int | |
55414b25 | 126 | search_findtype_partial(const uschar *name, int *ptypeptr, const uschar **ptypeaff, |
67a57a5a | 127 | int *afflen, int *starflags, const uschar ** opts) |
059ec3d9 PH |
128 | { |
129 | int len, stype; | |
130 | int pv = -1; | |
55414b25 | 131 | const uschar *ss = name; |
67a57a5a | 132 | const uschar * t; |
059ec3d9 PH |
133 | |
134 | *starflags = 0; | |
135 | *ptypeaff = NULL; | |
136 | ||
137 | /* Check for a partial matching type. It must start with "partial", optionally | |
138 | followed by a sequence of digits. If this is followed by "-", the affix is the | |
139 | default "*." string. Otherwise we expect an affix in parentheses. Affixes are a | |
140 | limited number of characters, not including parens. */ | |
141 | ||
142 | if (Ustrncmp(name, "partial", 7) == 0) | |
143 | { | |
144 | ss += 7; | |
145 | if (isdigit (*ss)) | |
146 | { | |
147 | pv = 0; | |
148 | while (isdigit(*ss)) pv = pv*10 + *ss++ - '0'; | |
149 | } | |
150 | else pv = 2; /* Default number of wild components */ | |
151 | ||
152 | if (*ss == '(') | |
153 | { | |
154 | *ptypeaff = ++ss; | |
155 | while (ispunct(*ss) && *ss != ')') ss++; | |
156 | if (*ss != ')') goto BAD_TYPE; | |
157 | *afflen = ss++ - *ptypeaff; | |
158 | } | |
159 | else if (*ss++ == '-') | |
160 | { | |
161 | *ptypeaff = US "*."; | |
162 | *afflen = 2; | |
163 | } | |
164 | else | |
165 | { | |
166 | BAD_TYPE: | |
167 | search_error_message = string_sprintf("format error in lookup type \"%s\"", | |
168 | name); | |
169 | return -1; | |
170 | } | |
171 | } | |
172 | ||
67a57a5a JH |
173 | /* Now we are left with a lookup name, possibly followed by * or *@, |
174 | and then by options starting with a "," */ | |
059ec3d9 | 175 | |
67a57a5a JH |
176 | len = Ustrlen(ss); |
177 | if ((t = Ustrchr(ss, '*'))) | |
178 | { | |
179 | len = t - ss; | |
180 | *starflags |= (t[1] == '@' ? SEARCH_STARAT : SEARCH_STAR); | |
181 | } | |
182 | else | |
183 | t = ss; | |
184 | ||
a5dc727a JH |
185 | if ((t = Ustrchr(t, ','))) |
186 | { | |
187 | int l = t - ss; | |
188 | if (l < len) len = l; | |
189 | *opts = string_copy(t+1); | |
190 | } | |
191 | else | |
0006e6d8 | 192 | *opts = NULL; |
059ec3d9 PH |
193 | |
194 | /* Check for the individual search type. Only those that are actually in the | |
d7837193 PH |
195 | binary are valid. For query-style types, "partial" and default types are |
196 | erroneous. */ | |
059ec3d9 PH |
197 | |
198 | stype = search_findtype(ss, len); | |
d7837193 | 199 | if (stype >= 0 && mac_islookup(stype, lookup_querystyle)) |
059ec3d9 | 200 | { |
d7837193 PH |
201 | if (pv >= 0) |
202 | { | |
203 | search_error_message = string_sprintf("\"partial\" is not permitted " | |
204 | "for lookup type \"%s\"", ss); | |
205 | return -1; | |
206 | } | |
207 | if ((*starflags & (SEARCH_STAR|SEARCH_STARAT)) != 0) | |
208 | { | |
209 | search_error_message = string_sprintf("defaults using \"*\" or \"*@\" are " | |
210 | "not permitted for lookup type \"%s\"", ss); | |
211 | return -1; | |
212 | } | |
059ec3d9 PH |
213 | } |
214 | ||
059ec3d9 PH |
215 | *ptypeptr = pv; |
216 | return stype; | |
217 | } | |
218 | ||
219 | ||
220 | ||
221 | /************************************************* | |
222 | * Release cached resources * | |
223 | *************************************************/ | |
224 | ||
225 | /* When search_open is called it caches the "file" that it opens in | |
226 | search_tree. The name of the tree node is a concatenation of the search type | |
227 | with the file name. For query-style lookups, the file name is empty. Real files | |
228 | are normally closed only when this tidyup routine is called, typically at the | |
229 | end of sections of code where a number of lookups might occur. However, if too | |
230 | many files are open simultaneously, some get closed beforehand. They can't be | |
231 | removed from the tree. There is also a general tidyup function which is called | |
232 | for the lookup driver, if it exists. | |
233 | ||
234 | First, there is an internal, recursive subroutine. | |
235 | ||
236 | Argument: a pointer to a search_openfile tree node | |
237 | Returns: nothing | |
238 | */ | |
239 | ||
240 | static void | |
241 | tidyup_subtree(tree_node *t) | |
242 | { | |
1950cf85 JH |
243 | search_cache * c = (search_cache *)(t->data.ptr); |
244 | if (t->left) tidyup_subtree(t->left); | |
245 | if (t->right) tidyup_subtree(t->right); | |
246 | if (c && c->handle && lookup_list[c->search_type]->close) | |
e6d225ae | 247 | lookup_list[c->search_type]->close(c->handle); |
059ec3d9 PH |
248 | } |
249 | ||
250 | ||
251 | /* The external entry point | |
252 | ||
253 | Argument: none | |
254 | Returns: nothing | |
255 | */ | |
256 | ||
257 | void | |
258 | search_tidyup(void) | |
259 | { | |
059ec3d9 PH |
260 | int old_pool = store_pool; |
261 | ||
42c7f0b4 | 262 | DEBUG(D_lookup) debug_printf_indent("search_tidyup called\n"); |
059ec3d9 PH |
263 | |
264 | /* Close individually each cached open file. */ | |
265 | ||
266 | store_pool = POOL_SEARCH; | |
d7978c0f | 267 | if (search_tree) |
059ec3d9 PH |
268 | { |
269 | tidyup_subtree(search_tree); | |
270 | search_tree = NULL; | |
271 | } | |
272 | open_top = open_bot = NULL; | |
273 | open_filecount = 0; | |
274 | ||
275 | /* Call the general tidyup entry for any drivers that have one. */ | |
276 | ||
d7978c0f JH |
277 | for (int i = 0; i < lookup_list_count; i++) if (lookup_list[i]->tidy) |
278 | (lookup_list[i]->tidy)(); | |
059ec3d9 | 279 | |
f3ebb786 | 280 | if (search_reset_point) search_reset_point = store_reset(search_reset_point); |
059ec3d9 PH |
281 | store_pool = old_pool; |
282 | } | |
283 | ||
284 | ||
285 | ||
286 | ||
287 | /************************************************* | |
288 | * Open search database * | |
289 | *************************************************/ | |
290 | ||
291 | /* A mode, and lists of owners and groups, are passed over for checking in | |
292 | the cases where the database is one or more files. Return NULL, with a message | |
293 | pointed to by message, in cases of error. | |
294 | ||
295 | For search types that use a file or files, check up on the mode after | |
296 | opening. It is tempting to do a stat before opening the file, and use it as | |
297 | an existence check. However, doing that opens a small security loophole in | |
298 | that the status could be changed before the file is opened. Can't quite see | |
299 | what problems this might lead to, but you can't be too careful where security | |
300 | is concerned. Fstat() on an open file can normally be expected to succeed, | |
301 | but there are some NFS states where it does not. | |
302 | ||
303 | There are two styles of query: (1) in the "single-key+file" style, a single | |
304 | key string and a file name are given, for example, for linear searches, DBM | |
305 | files, or for NIS. (2) In the "query" style, no "filename" is given; instead | |
306 | just a single query string is passed. This applies to multiple-key lookup | |
307 | types such as NIS+. | |
308 | ||
309 | Before opening, scan the tree of cached files to see if this file is already | |
310 | open for the correct search type. If so, return the saved handle. If not, put | |
311 | the handle in the tree for possible subsequent use. See search_tidyup above for | |
312 | closing all the cached files. | |
313 | ||
314 | A count of open databases which use real files is maintained, and if this | |
315 | gets too large, we have to close a cached file. Its entry remains in the tree, | |
316 | but is marked closed. | |
317 | ||
318 | Arguments: | |
319 | filename the name of the file for single-key+file style lookups, | |
320 | NULL for query-style lookups | |
321 | search_type the type of search required | |
322 | modemask if a real single file is used, this specifies mode bits that | |
323 | must not be set; otherwise it is ignored | |
324 | owners if a real single file is used, this specifies the possible | |
325 | owners of the file; otherwise it is ignored | |
326 | owngroups if a real single file is used, this specifies the possible | |
327 | group owners of the file; otherwise it is ignored | |
328 | ||
329 | Returns: an identifying handle for the open database; | |
330 | this is the pointer to the tree block in the | |
331 | cache of open files; return NULL on open failure, with | |
332 | a message in search_error_message | |
333 | */ | |
334 | ||
335 | void * | |
d447dbd1 JH |
336 | search_open(const uschar * filename, int search_type, int modemask, |
337 | uid_t * owners, gid_t * owngroups) | |
059ec3d9 PH |
338 | { |
339 | void *handle; | |
340 | tree_node *t; | |
341 | search_cache *c; | |
e6d225ae | 342 | lookup_info *lk = lookup_list[search_type]; |
059ec3d9 PH |
343 | uschar keybuffer[256]; |
344 | int old_pool = store_pool; | |
345 | ||
54a2a2a9 JH |
346 | if (filename && is_tainted(filename)) |
347 | { | |
348 | log_write(0, LOG_MAIN|LOG_PANIC, | |
349 | "Tainted filename for search: '%s'", filename); | |
350 | return NULL; | |
351 | } | |
352 | ||
059ec3d9 PH |
353 | /* Change to the search store pool and remember our reset point */ |
354 | ||
355 | store_pool = POOL_SEARCH; | |
f3ebb786 | 356 | if (!search_reset_point) search_reset_point = store_mark(); |
059ec3d9 | 357 | |
42c7f0b4 JH |
358 | DEBUG(D_lookup) debug_printf_indent("search_open: %s \"%s\"\n", lk->name, |
359 | filename ? filename : US"NULL"); | |
059ec3d9 PH |
360 | |
361 | /* See if we already have this open for this type of search, and if so, | |
362 | pass back the tree block as the handle. The key for the tree node is the search | |
363 | type plus '0' concatenated with the file name. There may be entries in the tree | |
364 | with closed files if a lot of files have been opened. */ | |
365 | ||
366 | sprintf(CS keybuffer, "%c%.254s", search_type + '0', | |
df04890c | 367 | filename ? filename : US""); |
059ec3d9 | 368 | |
df04890c | 369 | if ((t = tree_search(search_tree, keybuffer))) |
059ec3d9 | 370 | { |
54a2a2a9 | 371 | if ((c = (search_cache *)t->data.ptr)->handle) |
059ec3d9 | 372 | { |
42c7f0b4 | 373 | DEBUG(D_lookup) debug_printf_indent(" cached open\n"); |
059ec3d9 PH |
374 | store_pool = old_pool; |
375 | return t; | |
376 | } | |
42c7f0b4 | 377 | DEBUG(D_lookup) debug_printf_indent(" cached closed\n"); |
059ec3d9 PH |
378 | } |
379 | ||
380 | /* Otherwise, we need to open the file or database - each search type has its | |
381 | own code, which is now split off into separately compiled modules. Before doing | |
382 | this, if the search type is one that uses real files, check on the number that | |
383 | we are holding open in the cache. If the limit is reached, close the least | |
384 | recently used one. */ | |
385 | ||
386 | if (lk->type == lookup_absfile && open_filecount >= lookup_open_max) | |
df04890c | 387 | if (!open_bot) |
059ec3d9 PH |
388 | log_write(0, LOG_MAIN|LOG_PANIC, "too many lookups open, but can't find " |
389 | "one to close"); | |
390 | else | |
391 | { | |
392 | search_cache *c = (search_cache *)(open_bot->data.ptr); | |
42c7f0b4 | 393 | DEBUG(D_lookup) debug_printf_indent("Too many lookup files open\n closing %s\n", |
059ec3d9 | 394 | open_bot->name); |
df04890c | 395 | if ((open_bot = c->up)) |
059ec3d9 PH |
396 | ((search_cache *)(open_bot->data.ptr))->down = NULL; |
397 | else | |
398 | open_top = NULL; | |
e6d225ae | 399 | ((lookup_list[c->search_type])->close)(c->handle); |
059ec3d9 PH |
400 | c->handle = NULL; |
401 | open_filecount--; | |
402 | } | |
059ec3d9 PH |
403 | |
404 | /* If opening is successful, call the file-checking function if there is one, | |
405 | and if all is still well, enter the open database into the tree. */ | |
406 | ||
df04890c | 407 | if (!(handle = (lk->open)(filename, &search_error_message))) |
059ec3d9 PH |
408 | { |
409 | store_pool = old_pool; | |
410 | return NULL; | |
411 | } | |
412 | ||
df04890c JH |
413 | if ( lk->check |
414 | && !lk->check(handle, filename, modemask, owners, owngroups, | |
415 | &search_error_message)) | |
059ec3d9 PH |
416 | { |
417 | lk->close(handle); | |
418 | store_pool = old_pool; | |
419 | return NULL; | |
420 | } | |
421 | ||
422 | /* If this is a search type that uses real files, keep count. */ | |
423 | ||
424 | if (lk->type == lookup_absfile) open_filecount++; | |
425 | ||
426 | /* If we found a previously opened entry in the tree, re-use it; otherwise | |
427 | insert a new entry. On re-use, leave any cached lookup data and the lookup | |
428 | count alone. */ | |
429 | ||
df04890c | 430 | if (!t) |
059ec3d9 | 431 | { |
f3ebb786 JH |
432 | t = store_get(sizeof(tree_node) + Ustrlen(keybuffer), FALSE); |
433 | t->data.ptr = c = store_get(sizeof(search_cache), FALSE); | |
059ec3d9 PH |
434 | c->item_cache = NULL; |
435 | Ustrcpy(t->name, keybuffer); | |
436 | tree_insertnode(&search_tree, t); | |
437 | } | |
438 | else c = t->data.ptr; | |
439 | ||
440 | c->handle = handle; | |
441 | c->search_type = search_type; | |
442 | c->up = c->down = NULL; | |
443 | ||
444 | store_pool = old_pool; | |
445 | return t; | |
446 | } | |
447 | ||
448 | ||
449 | ||
450 | ||
451 | ||
452 | /************************************************* | |
453 | * Internal function: Find one item in database * | |
454 | *************************************************/ | |
455 | ||
456 | /* The answer is always put into dynamic store. The last lookup for each handle | |
457 | is cached. | |
458 | ||
459 | Arguments: | |
460 | handle the handle from search_open; points to tree node | |
461 | filename the filename that was handed to search_open, or | |
462 | NULL for query-style searches | |
463 | keystring the keystring for single-key+file lookups, or | |
464 | the querystring for query-style lookups | |
67a57a5a | 465 | opts type-specific options |
059ec3d9 PH |
466 | |
467 | Returns: a pointer to a dynamic string containing the answer, | |
468 | or NULL if the query failed or was deferred; in the | |
469 | latter case, search_find_defer is set TRUE; after an unusual | |
470 | failure, there may be a message in search_error_message. | |
471 | */ | |
472 | ||
473 | static uschar * | |
67a57a5a JH |
474 | internal_search_find(void * handle, const uschar * filename, uschar * keystring, |
475 | const uschar * opts) | |
059ec3d9 | 476 | { |
0488984d JH |
477 | tree_node * t = (tree_node *)handle; |
478 | search_cache * c = (search_cache *)(t->data.ptr); | |
479 | expiring_data * e = NULL; /* compiler quietening */ | |
480 | uschar * data = NULL; | |
059ec3d9 PH |
481 | int search_type = t->name[0] - '0'; |
482 | int old_pool = store_pool; | |
483 | ||
484 | /* Lookups that return DEFER may not always set an error message. So that | |
485 | the callers don't have to test for NULL, set an empty string. */ | |
486 | ||
487 | search_error_message = US""; | |
8768d548 | 488 | f.search_find_defer = FALSE; |
059ec3d9 | 489 | |
42c7f0b4 | 490 | DEBUG(D_lookup) debug_printf_indent("internal_search_find: file=\"%s\"\n " |
67a57a5a JH |
491 | "type=%s key=\"%s\" opts=%s%s%s\n", filename, |
492 | lookup_list[search_type]->name, keystring, | |
493 | opts ? "\"" : "", opts, opts ? "\"" : ""); | |
059ec3d9 PH |
494 | |
495 | /* Insurance. If the keystring is empty, just fail. */ | |
496 | ||
497 | if (keystring[0] == 0) return NULL; | |
498 | ||
499 | /* Use the special store pool for search data */ | |
500 | ||
501 | store_pool = POOL_SEARCH; | |
502 | ||
503 | /* Look up the data for the key, unless it is already in the cache for this | |
504 | file. No need to check c->item_cache for NULL, tree_search will do so. */ | |
505 | ||
14b3c5bc JH |
506 | if ( (t = tree_search(c->item_cache, keystring)) |
507 | && (!(e = t->data.ptr)->expiry || e->expiry > time(NULL)) | |
a5dc727a | 508 | && (!opts && !e->opts || opts && e->opts && Ustrcmp(opts, e->opts) == 0) |
14b3c5bc JH |
509 | ) |
510 | { /* Data was in the cache already; set the pointer from the tree node */ | |
7d8d08c4 | 511 | data = e->data.ptr; |
42c7f0b4 | 512 | DEBUG(D_lookup) debug_printf_indent("cached data used for lookup of %s%s%s\n", |
14b3c5bc JH |
513 | keystring, |
514 | filename ? US"\n in " : US"", filename ? filename : US""); | |
515 | } | |
516 | else | |
059ec3d9 | 517 | { |
14b3c5bc | 518 | uint do_cache = UINT_MAX; |
059ec3d9 PH |
519 | int keylength = Ustrlen(keystring); |
520 | ||
521 | DEBUG(D_lookup) | |
522 | { | |
a5dc727a | 523 | if (t) |
1950cf85 JH |
524 | debug_printf_indent("cached data found but %s; ", |
525 | e->expiry && e->expiry <= time(NULL) ? "out-of-date" : "wrong opts"); | |
42c7f0b4 | 526 | debug_printf_indent("%s lookup required for %s%s%s\n", |
14b3c5bc JH |
527 | filename ? US"file" : US"database", |
528 | keystring, | |
529 | filename ? US"\n in " : US"", filename ? filename : US""); | |
059ec3d9 PH |
530 | } |
531 | ||
532 | /* Call the code for the different kinds of search. DEFER is handled | |
533 | like FAIL, except that search_find_defer is set so the caller can | |
534 | distinguish if necessary. */ | |
535 | ||
e6d225ae | 536 | if (lookup_list[search_type]->find(c->handle, filename, keystring, keylength, |
67a57a5a | 537 | &data, &search_error_message, &do_cache, opts) == DEFER) |
8768d548 | 538 | f.search_find_defer = TRUE; |
059ec3d9 PH |
539 | |
540 | /* A record that has been found is now in data, which is either NULL | |
541 | or points to a bit of dynamic store. Cache the result of the lookup if | |
542 | caching is permitted. Lookups can disable caching, when they did something | |
543 | that changes their data. The mysql and pgsql lookups do this when an | |
544 | UPDATE/INSERT query was executed. */ | |
545 | ||
546 | else if (do_cache) | |
547 | { | |
1950cf85 | 548 | if (!t) /* No existing entry. Create new one. */ |
14b3c5bc | 549 | { |
92beef8b | 550 | int len = keylength + 1; |
f3ebb786 | 551 | e = store_get(sizeof(expiring_data) + sizeof(tree_node) + len, is_tainted(keystring)); |
98b98887 | 552 | t = (tree_node *)(e+1); |
14b3c5bc JH |
553 | memcpy(t->name, keystring, len); |
554 | t->data.ptr = e; | |
555 | tree_insertnode(&c->item_cache, t); | |
556 | } | |
92beef8b JH |
557 | /* Else previous, out-of-date cache entry. Update with the */ |
558 | /* new result and forget the old one */ | |
559 | e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; | |
1950cf85 | 560 | e->opts = opts ? string_copy(opts) : NULL; |
92beef8b | 561 | e->data.ptr = data; |
059ec3d9 PH |
562 | } |
563 | ||
564 | /* If caching was disabled, empty the cache tree. We just set the cache | |
565 | pointer to NULL here, because we cannot release the store at this stage. */ | |
566 | ||
567 | else | |
568 | { | |
42c7f0b4 | 569 | DEBUG(D_lookup) debug_printf_indent("lookup forced cache cleanup\n"); |
1950cf85 | 570 | c->item_cache = NULL; /* forget all lookups on this connection */ |
059ec3d9 PH |
571 | } |
572 | } | |
573 | ||
059ec3d9 PH |
574 | DEBUG(D_lookup) |
575 | { | |
14b3c5bc | 576 | if (data) |
42c7f0b4 | 577 | debug_printf_indent("lookup yielded: %s\n", data); |
8768d548 | 578 | else if (f.search_find_defer) |
42c7f0b4 JH |
579 | debug_printf_indent("lookup deferred: %s\n", search_error_message); |
580 | else debug_printf_indent("lookup failed\n"); | |
059ec3d9 PH |
581 | } |
582 | ||
583 | /* Return it in new dynamic store in the regular pool */ | |
584 | ||
585 | store_pool = old_pool; | |
14b3c5bc | 586 | return data ? string_copy(data) : NULL; |
059ec3d9 PH |
587 | } |
588 | ||
589 | ||
590 | ||
591 | ||
592 | /************************************************* | |
593 | * Find one item in database, possibly wildcarded * | |
594 | *************************************************/ | |
595 | ||
596 | /* This function calls the internal function above; once only if there | |
597 | is no partial matching, but repeatedly when partial matching is requested. | |
598 | ||
599 | Arguments: | |
600 | handle the handle from search_open | |
601 | filename the filename that was handed to search_open, or | |
602 | NULL for query-style searches | |
603 | keystring the keystring for single-key+file lookups, or | |
604 | the querystring for query-style lookups | |
605 | partial -1 means no partial matching; | |
606 | otherwise it's the minimum number of components; | |
607 | affix the affix string for partial matching | |
608 | affixlen the length of the affix string | |
609 | starflags SEARCH_STAR and SEARCH_STARAT flags | |
610 | expand_setup pointer to offset for setting up expansion strings; | |
611 | don't do any if < 0 | |
67a57a5a | 612 | opts type-specific options |
059ec3d9 PH |
613 | |
614 | Returns: a pointer to a dynamic string containing the answer, | |
615 | or NULL if the query failed or was deferred; in the | |
616 | latter case, search_find_defer is set TRUE | |
617 | */ | |
618 | ||
619 | uschar * | |
d447dbd1 JH |
620 | search_find(void * handle, const uschar * filename, uschar * keystring, |
621 | int partial, const uschar * affix, int affixlen, int starflags, | |
67a57a5a | 622 | int * expand_setup, const uschar * opts) |
059ec3d9 PH |
623 | { |
624 | tree_node *t = (tree_node *)handle; | |
625 | BOOL set_null_wild = FALSE; | |
626 | uschar *yield; | |
627 | ||
628 | DEBUG(D_lookup) | |
629 | { | |
630 | if (partial < 0) affixlen = 99; /* So that "NULL" prints */ | |
42c7f0b4 | 631 | debug_printf_indent("search_find: file=\"%s\"\n key=\"%s\" " |
67a57a5a JH |
632 | "partial=%d affix=%.*s starflags=%x opts=%s%s%s\n", |
633 | filename ? filename : US"NULL", | |
634 | keystring, partial, affixlen, affix, starflags, | |
635 | opts ? "\"" : "", opts, opts ? "\"" : ""); | |
636 | ||
059ec3d9 PH |
637 | } |
638 | ||
639 | /* Arrange to put this database at the top of the LRU chain if it is a type | |
640 | that opens real files. */ | |
641 | ||
df04890c JH |
642 | if ( open_top != (tree_node *)handle |
643 | && lookup_list[t->name[0]-'0']->type == lookup_absfile) | |
059ec3d9 PH |
644 | { |
645 | search_cache *c = (search_cache *)(t->data.ptr); | |
646 | tree_node *up = c->up; | |
647 | tree_node *down = c->down; | |
648 | ||
649 | /* Cut it out of the list. A newly opened file will a NULL up pointer. | |
650 | Otherwise there will be a non-NULL up pointer, since we checked above that | |
651 | this block isn't already at the top of the list. */ | |
652 | ||
df04890c | 653 | if (up) |
059ec3d9 PH |
654 | { |
655 | ((search_cache *)(up->data.ptr))->down = down; | |
df04890c | 656 | if (down) |
059ec3d9 | 657 | ((search_cache *)(down->data.ptr))->up = up; |
df04890c JH |
658 | else |
659 | open_bot = up; | |
059ec3d9 PH |
660 | } |
661 | ||
662 | /* Now put it at the head of the list. */ | |
663 | ||
664 | c->up = NULL; | |
665 | c->down = open_top; | |
df04890c JH |
666 | if (!open_top) open_bot = t; |
667 | else ((search_cache *)(open_top->data.ptr))->up = t; | |
059ec3d9 PH |
668 | open_top = t; |
669 | } | |
670 | ||
671 | DEBUG(D_lookup) | |
672 | { | |
42c7f0b4 JH |
673 | debug_printf_indent("LRU list:\n"); |
674 | for (tree_node *t = open_top; t; ) | |
059ec3d9 PH |
675 | { |
676 | search_cache *c = (search_cache *)(t->data.ptr); | |
42c7f0b4 JH |
677 | debug_printf_indent(" %s\n", t->name); |
678 | if (t == open_bot) debug_printf_indent(" End\n"); | |
059ec3d9 PH |
679 | t = c->down; |
680 | } | |
681 | } | |
682 | ||
683 | /* First of all, try to match the key string verbatim. If matched a complete | |
684 | entry but could have been partial, flag to set up variables. */ | |
685 | ||
67a57a5a | 686 | yield = internal_search_find(handle, filename, keystring, opts); |
8768d548 | 687 | if (f.search_find_defer) return NULL; |
df04890c JH |
688 | |
689 | if (yield) { if (partial >= 0) set_null_wild = TRUE; } | |
059ec3d9 PH |
690 | |
691 | /* Not matched a complete entry; handle partial lookups, but only if the full | |
692 | search didn't defer. Don't use string_sprintf() to construct the initial key, | |
693 | just in case the original key is too long for the string_sprintf() buffer (it | |
694 | *has* happened!). The case of a zero-length affix has to be treated specially. | |
695 | */ | |
696 | ||
697 | else if (partial >= 0) | |
698 | { | |
699 | int len = Ustrlen(keystring); | |
700 | uschar *keystring2; | |
701 | ||
702 | /* Try with the affix on the front, except for a zero-length affix */ | |
703 | ||
704 | if (affixlen == 0) keystring2 = keystring; else | |
705 | { | |
f3ebb786 JH |
706 | keystring2 = store_get(len + affixlen + 1, |
707 | is_tainted(keystring) || is_tainted(affix)); | |
059ec3d9 PH |
708 | Ustrncpy(keystring2, affix, affixlen); |
709 | Ustrcpy(keystring2 + affixlen, keystring); | |
42c7f0b4 | 710 | DEBUG(D_lookup) debug_printf_indent("trying partial match %s\n", keystring2); |
67a57a5a | 711 | yield = internal_search_find(handle, filename, keystring2, opts); |
8768d548 | 712 | if (f.search_find_defer) return NULL; |
059ec3d9 PH |
713 | } |
714 | ||
715 | /* The key in its entirety did not match a wild entry; try chopping off | |
716 | leading components. */ | |
717 | ||
0006e6d8 | 718 | if (!yield) |
059ec3d9 PH |
719 | { |
720 | int dotcount = 0; | |
721 | uschar *keystring3 = keystring2 + affixlen; | |
722 | uschar *s = keystring3; | |
723 | while (*s != 0) if (*s++ == '.') dotcount++; | |
724 | ||
725 | while (dotcount-- >= partial) | |
726 | { | |
727 | while (*keystring3 != 0 && *keystring3 != '.') keystring3++; | |
728 | ||
729 | /* If we get right to the end of the string (which will be the last time | |
730 | through this loop), we've failed if the affix is null. Otherwise do one | |
731 | last lookup for the affix itself, but if it is longer than 1 character, | |
732 | remove the last character if it is ".". */ | |
733 | ||
734 | if (*keystring3 == 0) | |
735 | { | |
736 | if (affixlen < 1) break; | |
737 | if (affixlen > 1 && affix[affixlen-1] == '.') affixlen--; | |
738 | Ustrncpy(keystring2, affix, affixlen); | |
739 | keystring2[affixlen] = 0; | |
740 | keystring3 = keystring2; | |
741 | } | |
742 | else | |
743 | { | |
744 | keystring3 -= affixlen - 1; | |
745 | if (affixlen > 0) Ustrncpy(keystring3, affix, affixlen); | |
746 | } | |
747 | ||
42c7f0b4 | 748 | DEBUG(D_lookup) debug_printf_indent("trying partial match %s\n", keystring3); |
67a57a5a | 749 | yield = internal_search_find(handle, filename, keystring3, opts); |
8768d548 | 750 | if (f.search_find_defer) return NULL; |
df04890c | 751 | if (yield) |
059ec3d9 PH |
752 | { |
753 | /* First variable is the wild part; second is the fixed part. Take care | |
754 | to get it right when keystring3 is just "*". */ | |
755 | ||
df04890c | 756 | if (expand_setup && *expand_setup >= 0) |
059ec3d9 PH |
757 | { |
758 | int fixedlength = Ustrlen(keystring3) - affixlen; | |
759 | int wildlength = Ustrlen(keystring) - fixedlength - 1; | |
760 | *expand_setup += 1; | |
761 | expand_nstring[*expand_setup] = keystring; | |
762 | expand_nlength[*expand_setup] = wildlength; | |
763 | *expand_setup += 1; | |
764 | expand_nstring[*expand_setup] = keystring + wildlength + 1; | |
765 | expand_nlength[*expand_setup] = (fixedlength < 0)? 0 : fixedlength; | |
766 | } | |
767 | break; | |
768 | } | |
769 | keystring3 += affixlen; | |
770 | } | |
771 | } | |
772 | ||
773 | else set_null_wild = TRUE; /* Matched a wild entry without any wild part */ | |
774 | } | |
775 | ||
776 | /* If nothing has been matched, but the option to look for "*@" is set, try | |
4c04137d | 777 | replacing everything to the left of @ by *. After a match, the wild part |
059ec3d9 PH |
778 | is set to the string to the left of the @. */ |
779 | ||
df04890c | 780 | if (!yield && starflags & SEARCH_STARAT) |
059ec3d9 PH |
781 | { |
782 | uschar *atat = Ustrrchr(keystring, '@'); | |
783 | if (atat != NULL && atat > keystring) | |
784 | { | |
785 | int savechar; | |
786 | savechar = *(--atat); | |
787 | *atat = '*'; | |
788 | ||
42c7f0b4 | 789 | DEBUG(D_lookup) debug_printf_indent("trying default match %s\n", atat); |
67a57a5a | 790 | yield = internal_search_find(handle, filename, atat, opts); |
059ec3d9 | 791 | *atat = savechar; |
8768d548 | 792 | if (f.search_find_defer) return NULL; |
059ec3d9 | 793 | |
df04890c | 794 | if (yield && expand_setup && *expand_setup >= 0) |
059ec3d9 PH |
795 | { |
796 | *expand_setup += 1; | |
797 | expand_nstring[*expand_setup] = keystring; | |
798 | expand_nlength[*expand_setup] = atat - keystring + 1; | |
799 | *expand_setup += 1; | |
800 | expand_nstring[*expand_setup] = keystring; | |
801 | expand_nlength[*expand_setup] = 0; | |
802 | } | |
803 | } | |
804 | } | |
805 | ||
806 | /* If we still haven't matched anything, and the option to look for "*" is set, | |
807 | try that. If we do match, the first variable (the wild part) is the whole key, | |
808 | and the second is empty. */ | |
809 | ||
df04890c | 810 | if (!yield && starflags & (SEARCH_STAR|SEARCH_STARAT)) |
059ec3d9 | 811 | { |
42c7f0b4 | 812 | DEBUG(D_lookup) debug_printf_indent("trying to match *\n"); |
67a57a5a | 813 | yield = internal_search_find(handle, filename, US"*", opts); |
df04890c | 814 | if (yield && expand_setup && *expand_setup >= 0) |
059ec3d9 PH |
815 | { |
816 | *expand_setup += 1; | |
817 | expand_nstring[*expand_setup] = keystring; | |
818 | expand_nlength[*expand_setup] = Ustrlen(keystring); | |
819 | *expand_setup += 1; | |
820 | expand_nstring[*expand_setup] = keystring; | |
821 | expand_nlength[*expand_setup] = 0; | |
822 | } | |
823 | } | |
824 | ||
825 | /* If this was a potentially partial lookup, and we matched either a | |
826 | complete non-wild domain entry, or we matched a wild-carded entry without | |
827 | chopping off any of the domain components, set up the expansion variables | |
828 | (if required) so that the first one is empty, and the second one is the | |
829 | fixed part of the domain. The set_null_wild flag is set only when yield is not | |
830 | NULL. */ | |
831 | ||
df04890c | 832 | if (set_null_wild && expand_setup && *expand_setup >= 0) |
059ec3d9 PH |
833 | { |
834 | *expand_setup += 1; | |
835 | expand_nstring[*expand_setup] = keystring; | |
836 | expand_nlength[*expand_setup] = 0; | |
837 | *expand_setup += 1; | |
838 | expand_nstring[*expand_setup] = keystring; | |
839 | expand_nlength[*expand_setup] = Ustrlen(keystring); | |
840 | } | |
841 | ||
0006e6d8 JH |
842 | /* If we have a result, check the options to see if the key was wanted rather |
843 | than the result. Return a de-tainted version of the key on the grounds that | |
844 | it have been validated by the lookup. */ | |
845 | ||
846 | if (yield && opts) | |
847 | { | |
848 | int sep = ','; | |
e541bb47 | 849 | for (uschar * ele; ele = string_nextinlist(&opts, &sep, NULL, 0); ) |
0006e6d8 | 850 | if (Ustrcmp(ele, "ret=key") == 0) |
e541bb47 JH |
851 | { |
852 | DEBUG(D_lookup) debug_printf_indent("lookup ret=key: %s\n", keystring); | |
853 | yield = string_copy_taint(keystring, FALSE); | |
854 | break; | |
855 | } | |
0006e6d8 JH |
856 | } |
857 | ||
059ec3d9 PH |
858 | return yield; |
859 | } | |
860 | ||
861 | /* End of search.c */ |