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 tree_node * lookups_tree = NULL;
23 unsigned lookup_list_count = 0;
25 /* Lists of information about which drivers are included in the exim binary. */
27 auth_info * auths_available= NULL;
28 router_info * routers_available = NULL;
29 transport_info * transports_available = NULL;
36 auth_show_supported(gstring * g)
38 uschar * b = US"" /* static-build authenticatornames */
39 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
42 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
45 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
48 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
51 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
54 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
57 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
60 #if defined(AUTH_SPA) && AUTH_SPA!=2
63 #if defined(AUTH_TLS) && AUTH_TLS!=2
68 uschar * d = US"" /* dynamic-module authenticator names */
69 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
72 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
75 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
78 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
81 #if defined(AUTH_GSASL) && AUTH_GSASL==2
84 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
87 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
90 #if defined(AUTH_SPA) && AUTH_SPA==2
93 #if defined(AUTH_TLS) && AUTH_TLS==2
98 if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
99 if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
104 route_show_supported(gstring * g)
106 uschar * b = US"" /* static-build router names */
107 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
110 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
113 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
116 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
119 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
122 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
125 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
130 uschar * d = US"" /* dynamic-module router names */
131 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
134 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
137 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
140 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
143 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
146 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
149 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
154 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
155 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
160 transport_show_supported(gstring * g)
162 uschar * b = US"" /* static-build transportnames */
163 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
165 # ifdef SUPPORT_MAILDIR
168 # ifdef SUPPORT_MAILSTORE
175 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
178 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
181 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
184 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
187 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
192 uschar * d = US"" /* dynamic-module transportnames */
193 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
195 # ifdef SUPPORT_MAILDIR
198 # ifdef SUPPORT_MAILSTORE
205 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
208 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
211 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
214 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
217 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
222 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
223 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
230 add_lookup_to_tree(lookup_info * li)
232 tree_node * new = store_get_perm(sizeof(tree_node) + Ustrlen(li->name),
234 new->data.ptr = (void *)li;
235 Ustrcpy(new->name, li->name);
236 if (tree_insertnode(&lookups_tree, new))
237 li->acq_num = lookup_list_count++;
239 log_write(0, LOG_MAIN|LOG_PANIC, "Duplicate lookup name '%s'", li->name);
243 /* Add all the lookup types provided by the module */
245 addlookupmodule(const struct lookup_module_info * lmi)
247 for (int j = 0; j < lmi->lookupcount; j++)
248 add_lookup_to_tree(lmi->lookups[j]);
253 /* Hunt for the lookup with the given acquisition number */
255 static unsigned hunt_acq;
258 acq_cb(uschar * name, uschar * ptr, void * ctx)
260 lookup_info * li = (lookup_info *)ptr;
261 if (li->acq_num == hunt_acq) *(lookup_info **)ctx = li;
265 lookup_with_acq_num(unsigned k)
267 const lookup_info * li = NULL;
269 tree_walk(lookups_tree, acq_cb, &li);
275 /* These need to be at file level for old versions of gcc (2.95.2 reported),
276 which give parse errors on an extern in function scope. Each entry needs
277 to also be invoked in init_lookup_list() below */
279 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
280 extern lookup_module_info cdb_lookup_module_info;
282 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
283 extern lookup_module_info dbmdb_lookup_module_info;
285 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
286 extern lookup_module_info dnsdb_lookup_module_info;
288 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
289 extern lookup_module_info dsearch_lookup_module_info;
291 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
292 extern lookup_module_info ibase_lookup_module_info;
294 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
295 extern lookup_module_info json_lookup_module_info;
297 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
298 extern lookup_module_info ldap_lookup_module_info;
300 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
301 extern lookup_module_info lsearch_lookup_module_info;
303 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
304 extern lookup_module_info mysql_lookup_module_info;
306 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
307 extern lookup_module_info nis_lookup_module_info;
309 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
310 extern lookup_module_info nisplus_lookup_module_info;
312 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
313 extern lookup_module_info oracle_lookup_module_info;
315 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
316 extern lookup_module_info passwd_lookup_module_info;
318 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
319 extern lookup_module_info pgsql_lookup_module_info;
321 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
322 extern lookup_module_info redis_lookup_module_info;
324 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
325 extern lookup_module_info lmdb_lookup_module_info;
327 #if defined(SUPPORT_SPF)
328 extern lookup_module_info spf_lookup_module_info; /* see below */
330 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
331 extern lookup_module_info sqlite_lookup_module_info;
333 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
334 extern lookup_module_info testdb_lookup_module_info;
336 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
337 extern lookup_module_info whoson_lookup_module_info;
340 extern lookup_module_info readsock_lookup_module_info;
343 #ifdef LOOKUP_MODULE_DIR
345 mod_open(const uschar * name, const uschar * class, uschar ** errstr)
347 const uschar * path = string_sprintf(
348 LOOKUP_MODULE_DIR "/%s_%s." DYNLIB_FN_EXT, name, class);
350 if (!(dl = dlopen(CS path, RTLD_NOW)))
353 *errstr = string_sprintf("Error loading %s: %s", name, dlerror());
355 (void) dlerror(); /* clear out error state */
359 /* FreeBSD nsdispatch() can trigger dlerror() errors about
360 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
361 state before calling dlsym(), so that any error afterwards only comes
369 /* Try to load a lookup module with the given name.
372 name name of the lookup
373 errstr if not NULL, place "open fail" error message here
375 Return: boolean success
379 lookup_mod_load(const uschar * name, uschar ** errstr)
382 struct lookup_module_info * info;
383 const char * errormsg;
385 if (!(dl = mod_open(name, US"lookup", errstr)))
388 info = (struct lookup_module_info *) dlsym(dl, "_lookup_module_info");
389 if ((errormsg = dlerror()))
391 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
392 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)", name, errormsg);
396 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
398 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
399 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim", name);
404 addlookupmodule(info);
405 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\" (%d lookup type%s)\n",
406 name, info->lookupcount,
407 info->lookupcount > 1 ? "s" : "");
412 /* Try to load a lookup module, assuming the module name is the same
413 as the lookup type name. This will only work for single-method modules.
414 Other have to be always-load (see the RE in init_lookup_list() below).
418 lookup_one_mod_load(const uschar * name, uschar ** errstr)
420 if (!lookup_mod_load(name, errstr)) return FALSE;
421 /*XXX notify daemon? */
425 #endif /*LOOKUP_MODULE_DIR*/
429 misc_module_info * misc_module_list = NULL;
432 misc_mod_add(misc_module_info * mi)
434 if (mi->init && mi->init(mi))
436 DEBUG(D_any) if (mi->lib_vers_report)
437 debug_printf_indent("%Y", mi->lib_vers_report(NULL));
439 mi->next = misc_module_list;
440 misc_module_list = mi;
443 debug_printf_indent("module init call failed for %s\n", mi->name);
444 /* fprintf(stderr,"misc_mod_add: added %s\n", mi->name); */
448 #ifdef LOOKUP_MODULE_DIR
450 /* Load a "misc" module, and add to list */
452 static misc_module_info *
453 misc_mod_load(const uschar * name, uschar ** errstr)
456 struct misc_module_info * mi;
457 const char * errormsg;
459 DEBUG(D_any) debug_printf_indent("loading module '%s'\n", name);
460 if (!(dl = mod_open(name, US"miscmod", errstr)))
462 DEBUG(D_any) debug_printf_indent(" mod_open: %s\n", *errstr);
466 mi = (struct misc_module_info *) dlsym(dl,
467 CS string_sprintf("%s_module_info", name));
468 if ((errormsg = dlerror()))
470 fprintf(stderr, "%s does not appear to be a '%s' module (%s)\n",
471 name, name, errormsg);
472 log_write(0, LOG_MAIN|LOG_PANIC,
473 "%s does not contain the expected module info symbol (%s)", name, errormsg);
477 if (mi->dyn_magic != MISC_MODULE_MAGIC)
479 fprintf(stderr, "Module %s is not compatible with this version of Exim\n", name);
480 log_write(0, LOG_MAIN|LOG_PANIC, "Module %s is not compatible with this version of Exim", name);
485 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\"\n", name);
490 #endif /*LOOKUP_MODULE_DIR*/
493 /* Find a "misc" module by name, if loaded.
494 For now use a linear search down a linked list. If the number of
495 modules gets large, we might consider a tree.
499 misc_mod_findonly(const uschar * name)
501 for (misc_module_info * mi = misc_module_list; mi; mi = mi->next)
502 if (Ustrcmp(name, mi->name) == 0)
507 /* Find a "misc" module, possibly already loaded, by name. */
510 misc_mod_find(const uschar * name, uschar ** errstr)
512 misc_module_info * mi;
513 if ((mi = misc_mod_findonly(name))) return mi;
514 #ifdef LOOKUP_MODULE_DIR
515 return misc_mod_load(name, errstr);
518 #endif /*LOOKUP_MODULE_DIR*/
522 /* For any "misc" module having a connection-init routine, call it. */
525 misc_mod_conn_init(const uschar * sender_helo_name,
526 const uschar * sender_host_address)
528 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
530 if ((mi->conn_init) (sender_helo_name, sender_host_address) != OK)
535 /* Ditto, smtp-reset */
538 misc_mod_smtp_reset(void)
540 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
545 /* Ditto, msg-init */
548 misc_mod_msg_init(void)
550 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
552 if ((mi->msg_init)() != OK)
557 /* Ditto, authres. Having to sort the responses (mainly for the testsuite)
558 is pretty painful - maybe we should sort the modules on insertion to
562 misc_mod_authres(gstring * g)
569 {US"spf", NULL}, {US"dkim", NULL}, {US"dmarc", NULL}, {US"arc", NULL}
571 gstring * others = NULL;
573 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
577 for (p = prefs; p < prefs + nelem(prefs); p++)
578 if (Ustrcmp(p->name, mi->name) == 0) break;
580 if (p) p->res = (mi->authres)(NULL);
581 else others = (mi->authres)(others);
584 for (pref * p = prefs; p < prefs + nelem(prefs); p++)
585 g = gstring_append(g, p->res);
586 return gstring_append(g, others);
595 init_lookup_list(void)
597 #ifdef LOOKUP_MODULE_DIR
599 int countmodules = 0;
601 static BOOL lookup_list_init_done = FALSE;
603 if (lookup_list_init_done)
605 lookup_list_init_done = TRUE;
607 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
608 addlookupmodule(&cdb_lookup_module_info);
611 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
612 addlookupmodule(&dbmdb_lookup_module_info);
615 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
616 addlookupmodule(&dnsdb_lookup_module_info);
619 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
620 addlookupmodule(&dsearch_lookup_module_info);
623 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
624 addlookupmodule(&ibase_lookup_module_info);
627 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
628 addlookupmodule(&ldap_lookup_module_info);
631 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
632 addlookupmodule(&json_lookup_module_info);
635 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
636 addlookupmodule(&lsearch_lookup_module_info);
639 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
640 addlookupmodule(&mysql_lookup_module_info);
643 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
644 addlookupmodule(&nis_lookup_module_info);
647 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
648 addlookupmodule(&nisplus_lookup_module_info);
651 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
652 addlookupmodule(&oracle_lookup_module_info);
655 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
656 addlookupmodule(&passwd_lookup_module_info);
659 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
660 addlookupmodule(&pgsql_lookup_module_info);
663 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
664 addlookupmodule(&redis_lookup_module_info);
667 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
668 addlookupmodule(&lmdb_lookup_module_info);
671 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
672 addlookupmodule(&sqlite_lookup_module_info);
675 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
676 addlookupmodule(&testdb_lookup_module_info);
679 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
680 addlookupmodule(&whoson_lookup_module_info);
683 /* This is provided by the spf "misc" module, and the lookup aspect is always
684 linked statically whether or not the "misc" module (and hence libspf2) is
687 #if defined(SUPPORT_SPF)
688 addlookupmodule(&spf_lookup_module_info);
691 /* This is a custom expansion, and not available as either
692 a list-syntax lookup or a lookup expansion. However, it is
693 implemented by a lookup module. */
695 addlookupmodule(&readsock_lookup_module_info);
697 DEBUG(D_lookup) debug_printf("Total %d built-in lookups\n", lookup_list_count);
700 #ifdef LOOKUP_MODULE_DIR
701 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
703 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
704 log_write(0, LOG_MAIN|LOG_PANIC,
705 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
709 /* Look specifically for modules we know offer several lookup types and
710 load them now, since we cannot load-on-first-use. */
713 const pcre2_code * regex_islookupmod = regex_must_compile(
714 US"(lsearch|ldap|nis)_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
716 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
717 while ((ent = readdir(dd)))
719 char * name = ent->d_name;
720 int len = (int)strlen(name);
721 if (regex_match_and_setup(regex_islookupmod, US name, 0, 0))
724 if (lookup_mod_load(expand_nstring[1], &errstr))
728 fprintf(stderr, "%s\n", errstr);
729 log_write(0, LOG_MAIN|LOG_PANIC, "%s", errstr);
736 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
741 /* Add module info struct to the modules list for those that are
744 #if !defined(DISABLE_DKIM) && (!defined(SUPPORT_DKIM) || SUPPORT_DKIM!=2)
745 extern misc_module_info dkim_module_info;
747 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
748 extern misc_module_info dmarc_module_info;
750 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
751 extern misc_module_info spf_module_info;
753 #if defined(EXPERIMENTAL_ARC) && (!defined(SUPPORT_ARC) || SUPPORT_ARC!=2)
754 extern misc_module_info arc_module_info;
756 #if defined(RADIUS_CONFIG_FILE) && (!defined(SUPPORT_RADIUS) || SUPPORT_RADUIS!=2)
757 extern misc_module_info radius_module_info;
759 #if defined(SUPPORT_PAM) && SUPPORT_PAM!=2
760 extern misc_module_info pam_module_info;
764 init_misc_mod_list(void)
766 static BOOL onetime = FALSE;
770 #if !defined(DISABLE_DKIM) && (!defined(SUPPORT_DKIM) || SUPPORT_DKIM!=2)
771 misc_mod_add(&dkim_module_info);
773 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
774 misc_mod_add(&spf_module_info);
776 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
777 /* dmarc depends on spf so this add must go after, for the both-static case */
778 misc_mod_add(&dmarc_module_info);
780 #if defined(EXPERIMENTAL_ARC) && (!defined(SUPPORT_ARC) || SUPPORT_ARC!=2)
781 misc_mod_add(&arc_module_info);
783 #if defined(RADIUS_CONFIG_FILE) && (!defined(SUPPORT_RADIUS) || SUPPORT_RADUIS!=2)
784 misc_mod_add(&radius_module_info);
786 #if defined(SUPPORT_PAM) && SUPPORT_PAM!=2
787 misc_mod_add(&pam_module_info);
792 #endif /*!MACRO_PREDEF*/
793 /* End of drtables.c */