1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
15 /* This module contains tables that define the lookup methods and drivers
16 that are actually included in the binary. Its contents are controlled by
17 various macros in config.h that ultimately come from Local/Makefile. They are
18 all described in src/EDITME. */
21 lookup_info **lookup_list;
22 int lookup_list_count = 0;
24 /* Lists of information about which drivers are included in the exim binary. */
26 auth_info * auths_available= NULL;
27 router_info * routers_available = NULL;
28 transport_info * transports_available = NULL;
35 auth_show_supported(gstring * g)
37 uschar * b = US"" /* static-build authenticatornames */
38 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
41 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
44 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
47 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
50 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
53 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
56 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
59 #if defined(AUTH_SPA) && AUTH_SPA!=2
62 #if defined(AUTH_TLS) && AUTH_TLS!=2
67 uschar * d = US"" /* dynamic-module authenticator names */
68 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
71 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
74 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
77 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
80 #if defined(AUTH_GSASL) && AUTH_GSASL==2
83 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
86 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
89 #if defined(AUTH_SPA) && AUTH_SPA==2
92 #if defined(AUTH_TLS) && AUTH_TLS==2
97 if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
98 if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
103 route_show_supported(gstring * g)
105 uschar * b = US"" /* static-build router names */
106 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
109 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
112 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
115 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
118 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
121 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
124 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
129 uschar * d = US"" /* dynamic-module router names */
130 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
133 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
136 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
139 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
142 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
145 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
148 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
153 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
154 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
159 transport_show_supported(gstring * g)
161 uschar * b = US"" /* static-build transportnames */
162 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
164 # ifdef SUPPORT_MAILDIR
167 # ifdef SUPPORT_MAILSTORE
174 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
177 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
180 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
183 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
186 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
191 uschar * d = US"" /* dynamic-module transportnames */
192 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
194 # ifdef SUPPORT_MAILDIR
197 # ifdef SUPPORT_MAILSTORE
204 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
207 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
210 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
213 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
216 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
221 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
222 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
228 struct lookupmodulestr
231 struct lookup_module_info *info;
232 struct lookupmodulestr *next;
235 static struct lookupmodulestr *lookupmodules = NULL;
238 addlookupmodule(void *dl, struct lookup_module_info *info)
240 struct lookupmodulestr * p =
241 store_get(sizeof(struct lookupmodulestr), GET_UNTAINTED);
245 p->next = lookupmodules;
247 lookup_list_count += info->lookupcount;
250 /* only valid after lookup_list and lookup_list_count are assigned */
252 add_lookup_to_list(lookup_info *info)
254 /* need to add the lookup to lookup_list, sorted */
257 /* strategy is to go through the list until we find
258 either an empty spot or a name that is higher.
259 this can't fail because we have enough space. */
261 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
264 if (lookup_list[pos])
266 /* need to insert it, so move all the other items up
267 (last slot is still empty, of course) */
269 memmove(&lookup_list[pos+1], &lookup_list[pos],
270 sizeof(lookup_info *) * (lookup_list_count-pos-1));
272 lookup_list[pos] = info;
276 /* These need to be at file level for old versions of gcc (2.95.2 reported),
277 which give parse errors on an extern in function scope. Each entry needs
278 to also be invoked in init_lookup_list() below */
280 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
281 extern lookup_module_info cdb_lookup_module_info;
283 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
284 extern lookup_module_info dbmdb_lookup_module_info;
286 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
287 extern lookup_module_info dnsdb_lookup_module_info;
289 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
290 extern lookup_module_info dsearch_lookup_module_info;
292 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
293 extern lookup_module_info ibase_lookup_module_info;
295 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
296 extern lookup_module_info json_lookup_module_info;
298 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
299 extern lookup_module_info ldap_lookup_module_info;
301 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
302 extern lookup_module_info lsearch_lookup_module_info;
304 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
305 extern lookup_module_info mysql_lookup_module_info;
307 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
308 extern lookup_module_info nis_lookup_module_info;
310 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
311 extern lookup_module_info nisplus_lookup_module_info;
313 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
314 extern lookup_module_info oracle_lookup_module_info;
316 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
317 extern lookup_module_info passwd_lookup_module_info;
319 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
320 extern lookup_module_info pgsql_lookup_module_info;
322 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
323 extern lookup_module_info redis_lookup_module_info;
325 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
326 extern lookup_module_info lmdb_lookup_module_info;
328 #if defined(SUPPORT_SPF)
329 extern lookup_module_info spf_lookup_module_info;
331 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
332 extern lookup_module_info sqlite_lookup_module_info;
334 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
335 extern lookup_module_info testdb_lookup_module_info;
337 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
338 extern lookup_module_info whoson_lookup_module_info;
341 extern lookup_module_info readsock_lookup_module_info;
345 init_lookup_list(void)
347 #ifdef LOOKUP_MODULE_DIR
350 int countmodules = 0;
351 int moduleerrors = 0;
353 static BOOL lookup_list_init_done = FALSE;
356 if (lookup_list_init_done)
358 reset_point = store_mark();
359 lookup_list_init_done = TRUE;
361 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
362 addlookupmodule(NULL, &cdb_lookup_module_info);
365 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
366 addlookupmodule(NULL, &dbmdb_lookup_module_info);
369 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
370 addlookupmodule(NULL, &dnsdb_lookup_module_info);
373 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
374 addlookupmodule(NULL, &dsearch_lookup_module_info);
377 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
378 addlookupmodule(NULL, &ibase_lookup_module_info);
381 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
382 addlookupmodule(NULL, &ldap_lookup_module_info);
385 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
386 addlookupmodule(NULL, &json_lookup_module_info);
389 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
390 addlookupmodule(NULL, &lsearch_lookup_module_info);
393 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
394 addlookupmodule(NULL, &mysql_lookup_module_info);
397 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
398 addlookupmodule(NULL, &nis_lookup_module_info);
401 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
402 addlookupmodule(NULL, &nisplus_lookup_module_info);
405 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
406 addlookupmodule(NULL, &oracle_lookup_module_info);
409 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
410 addlookupmodule(NULL, &passwd_lookup_module_info);
413 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
414 addlookupmodule(NULL, &pgsql_lookup_module_info);
417 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
418 addlookupmodule(NULL, &redis_lookup_module_info);
421 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
422 addlookupmodule(NULL, &lmdb_lookup_module_info);
426 addlookupmodule(NULL, &spf_lookup_module_info);
429 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
430 addlookupmodule(NULL, &sqlite_lookup_module_info);
433 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
434 addlookupmodule(NULL, &testdb_lookup_module_info);
437 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
438 addlookupmodule(NULL, &whoson_lookup_module_info);
441 /* This is a custom expansion, and not available as either
442 a list-syntax lookup or a lookup expansion. However, it is
443 implemented by a lookup module. */
445 addlookupmodule(NULL, &readsock_lookup_module_info);
447 #ifdef LOOKUP_MODULE_DIR
448 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
450 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
451 log_write(0, LOG_MAIN|LOG_PANIC,
452 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
456 const pcre2_code * regex_islookupmod = regex_must_compile(
457 US"_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
459 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
460 while ((ent = readdir(dd)))
462 char * name = ent->d_name;
463 int len = (int)strlen(name);
464 if (regex_match(regex_islookupmod, US name, len, NULL))
466 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
468 struct lookup_module_info *info;
469 const char *errormsg;
471 /* SRH: am I being paranoid here or what? */
472 if (pathnamelen > big_buffer_size)
474 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
475 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
479 /* SRH: snprintf here? */
480 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
482 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
484 errormsg = dlerror();
485 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
486 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
491 /* FreeBSD nsdispatch() can trigger dlerror() errors about
492 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
493 state before calling dlsym(), so that any error afterwards only comes
496 errormsg = dlerror();
498 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
499 if ((errormsg = dlerror()))
501 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
502 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
507 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
509 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
510 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
516 addlookupmodule(dl, info);
517 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
521 store_free((void*)regex_islookupmod);
525 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
528 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
530 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
531 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
533 /* now add all lookups to the real list */
534 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
535 for (int j = 0; j < p->info->lookupcount; j++)
536 add_lookup_to_list(p->info->lookups[j]);
537 store_reset(reset_point);
538 /* just to be sure */
539 lookupmodules = NULL;
542 #endif /*!MACRO_PREDEF*/
543 /* End of drtables.c */