1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2023 */
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 /* Table of information about all possible authentication mechanisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set to NULL for those that are not compiled into the binary. */
29 #include "auths/cram_md5.h"
32 #ifdef AUTH_CYRUS_SASL
33 #include "auths/cyrus_sasl.h"
37 #include "auths/dovecot.h"
41 #include "auths/external.h"
45 #include "auths/gsasl_exim.h"
48 #ifdef AUTH_HEIMDAL_GSSAPI
49 #include "auths/heimdal_gssapi.h"
53 #include "auths/plaintext.h"
57 #include "auths/spa.h"
61 #include "auths/tls.h"
64 auth_info * auths_available_newlist = NULL;
65 auth_info auths_available_oldarray[] = {
67 /* Checking by an expansion condition on plain text */
72 .driver_name = US"cram_md5", /* lookup name */
73 .options = auth_cram_md5_options,
74 .options_count = &auth_cram_md5_options_count,
75 .options_block = &auth_cram_md5_option_defaults,
76 .options_len = sizeof(auth_cram_md5_options_block),
77 .init = auth_cram_md5_init,
79 .servercode = auth_cram_md5_server,
80 .clientcode = auth_cram_md5_client,
81 .version_report = NULL,
82 .macros_create = NULL,
86 #ifdef AUTH_CYRUS_SASL
89 .driver_name = US"cyrus_sasl",
90 .options = auth_cyrus_sasl_options,
91 .options_count = &auth_cyrus_sasl_options_count,
92 .options_block = &auth_cyrus_sasl_option_defaults,
93 .options_len = sizeof(auth_cyrus_sasl_options_block),
94 .init = auth_cyrus_sasl_init,
96 .servercode = auth_cyrus_sasl_server,
98 .version_report = auth_cyrus_sasl_version_report,
99 .macros_create = NULL,
106 .driver_name = US"dovecot",
107 .options = auth_dovecot_options,
108 .options_count = &auth_dovecot_options_count,
109 .options_block = &auth_dovecot_option_defaults,
110 .options_len = sizeof(auth_dovecot_options_block),
111 .init = auth_dovecot_init,
113 .servercode = auth_dovecot_server,
115 .version_report = NULL,
116 .macros_create = NULL,
123 .driver_name = US"external",
124 .options = auth_external_options,
125 .options_count = &auth_external_options_count,
126 .options_block = &auth_external_option_defaults,
127 .options_len = sizeof(auth_external_options_block),
128 .init = auth_external_init,
130 .servercode = auth_external_server,
131 .clientcode = auth_external_client,
132 .version_report = NULL,
133 .macros_create = NULL,
140 .driver_name = US"gsasl",
141 .options = auth_gsasl_options,
142 .options_count = &auth_gsasl_options_count,
143 .options_block = &auth_gsasl_option_defaults,
144 .options_len = sizeof(auth_gsasl_options_block),
145 .init = auth_gsasl_init,
147 .servercode = auth_gsasl_server,
148 .clientcode = auth_gsasl_client,
149 .version_report = auth_gsasl_version_report,
150 .macros_create = auth_gsasl_macros,
154 #ifdef AUTH_HEIMDAL_GSSAPI
157 .driver_name = US"heimdal_gssapi",
158 .options = auth_heimdal_gssapi_options,
159 .options_count = &auth_heimdal_gssapi_options_count,
160 .options_block = &auth_heimdal_gssapi_option_defaults,
161 .options_len = sizeof(auth_heimdal_gssapi_options_block),
162 .init = auth_heimdal_gssapi_init,
164 .servercode = auth_heimdal_gssapi_server,
166 .version_report = auth_heimdal_gssapi_version_report,
167 .macros_create = NULL,
171 #ifdef AUTH_PLAINTEXT
174 .driver_name = US"plaintext",
175 .options = auth_plaintext_options,
176 .options_count = &auth_plaintext_options_count,
177 .options_block = &auth_plaintext_option_defaults,
178 .options_len = sizeof(auth_plaintext_options_block),
179 .init = auth_plaintext_init,
181 .servercode = auth_plaintext_server,
182 .clientcode = auth_plaintext_client,
183 .version_report = NULL,
184 .macros_create = NULL,
191 .driver_name = US"spa",
192 .options = auth_spa_options,
193 .options_count = &auth_spa_options_count,
194 .options_block = &auth_spa_option_defaults,
195 .options_len = sizeof(auth_spa_options_block),
196 .init = auth_spa_init,
198 .servercode = auth_spa_server,
199 .clientcode = auth_spa_client,
200 .version_report = NULL,
201 .macros_create = NULL,
208 .driver_name = US"tls",
209 .options = auth_tls_options,
210 .options_count = &auth_tls_options_count,
211 .options_block = &auth_tls_option_defaults,
212 .options_len = sizeof(auth_tls_options_block),
213 .init = auth_tls_init,
215 .servercode = auth_tls_server,
217 .version_report = NULL,
218 .macros_create = NULL,
222 { .drinfo = { .driver_name = US"" }} /* end marker */
226 /* Tables of information about which routers and transports are included in the
229 /* Pull in the necessary header files */
231 #include "routers/rf_functions.h"
234 router_info * routers_available = NULL;
235 transport_info * transports_available = NULL;
242 auth_show_supported(gstring * g)
244 g = string_cat(g, US"Authenticators:");
245 for (auth_info * ai = auths_available_oldarray; ai->drinfo.driver_name[0]; ai++)
246 g = string_fmt_append(g, " %s", ai->drinfo.driver_name);
247 return string_cat(g, US"\n");
251 route_show_supported(gstring * g)
253 uschar * b = US"" /* static-build router names */
254 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
257 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
260 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
263 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
266 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
269 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
272 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
277 uschar * d = US"" /* dynamic-module router names */
278 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
281 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
284 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
287 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
290 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
293 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
296 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
301 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
302 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
307 transport_show_supported(gstring * g)
309 uschar * b = US"" /* static-build transportnames */
310 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
312 # ifdef SUPPORT_MAILDIR
315 # ifdef SUPPORT_MAILSTORE
322 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
325 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
328 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
331 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
334 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
339 uschar * d = US"" /* dynamic-module transportnames */
340 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
342 # ifdef SUPPORT_MAILDIR
345 # ifdef SUPPORT_MAILSTORE
352 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
355 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
358 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
361 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
364 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
369 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
370 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
376 struct lookupmodulestr
379 struct lookup_module_info *info;
380 struct lookupmodulestr *next;
383 static struct lookupmodulestr *lookupmodules = NULL;
386 addlookupmodule(void *dl, struct lookup_module_info *info)
388 struct lookupmodulestr * p =
389 store_get(sizeof(struct lookupmodulestr), GET_UNTAINTED);
393 p->next = lookupmodules;
395 lookup_list_count += info->lookupcount;
398 /* only valid after lookup_list and lookup_list_count are assigned */
400 add_lookup_to_list(lookup_info *info)
402 /* need to add the lookup to lookup_list, sorted */
405 /* strategy is to go through the list until we find
406 either an empty spot or a name that is higher.
407 this can't fail because we have enough space. */
409 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
412 if (lookup_list[pos])
414 /* need to insert it, so move all the other items up
415 (last slot is still empty, of course) */
417 memmove(&lookup_list[pos+1], &lookup_list[pos],
418 sizeof(lookup_info *) * (lookup_list_count-pos-1));
420 lookup_list[pos] = info;
424 /* These need to be at file level for old versions of gcc (2.95.2 reported),
425 which give parse errors on an extern in function scope. Each entry needs
426 to also be invoked in init_lookup_list() below */
428 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
429 extern lookup_module_info cdb_lookup_module_info;
431 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
432 extern lookup_module_info dbmdb_lookup_module_info;
434 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
435 extern lookup_module_info dnsdb_lookup_module_info;
437 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
438 extern lookup_module_info dsearch_lookup_module_info;
440 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
441 extern lookup_module_info ibase_lookup_module_info;
443 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
444 extern lookup_module_info json_lookup_module_info;
446 #if defined(LOOKUP_LDAP)
447 extern lookup_module_info ldap_lookup_module_info;
449 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
450 extern lookup_module_info lsearch_lookup_module_info;
452 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
453 extern lookup_module_info mysql_lookup_module_info;
455 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
456 extern lookup_module_info nis_lookup_module_info;
458 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
459 extern lookup_module_info nisplus_lookup_module_info;
461 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
462 extern lookup_module_info oracle_lookup_module_info;
464 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
465 extern lookup_module_info passwd_lookup_module_info;
467 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
468 extern lookup_module_info pgsql_lookup_module_info;
470 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
471 extern lookup_module_info redis_lookup_module_info;
473 #if defined(LOOKUP_LMDB)
474 extern lookup_module_info lmdb_lookup_module_info;
476 #if defined(SUPPORT_SPF)
477 extern lookup_module_info spf_lookup_module_info;
479 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
480 extern lookup_module_info sqlite_lookup_module_info;
482 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
483 extern lookup_module_info testdb_lookup_module_info;
485 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
486 extern lookup_module_info whoson_lookup_module_info;
489 extern lookup_module_info readsock_lookup_module_info;
493 init_lookup_list(void)
495 #ifdef LOOKUP_MODULE_DIR
498 int countmodules = 0;
499 int moduleerrors = 0;
501 static BOOL lookup_list_init_done = FALSE;
504 if (lookup_list_init_done)
506 reset_point = store_mark();
507 lookup_list_init_done = TRUE;
509 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
510 addlookupmodule(NULL, &cdb_lookup_module_info);
513 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
514 addlookupmodule(NULL, &dbmdb_lookup_module_info);
517 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
518 addlookupmodule(NULL, &dnsdb_lookup_module_info);
521 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
522 addlookupmodule(NULL, &dsearch_lookup_module_info);
525 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
526 addlookupmodule(NULL, &ibase_lookup_module_info);
530 addlookupmodule(NULL, &ldap_lookup_module_info);
533 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
534 addlookupmodule(NULL, &json_lookup_module_info);
537 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
538 addlookupmodule(NULL, &lsearch_lookup_module_info);
541 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
542 addlookupmodule(NULL, &mysql_lookup_module_info);
545 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
546 addlookupmodule(NULL, &nis_lookup_module_info);
549 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
550 addlookupmodule(NULL, &nisplus_lookup_module_info);
553 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
554 addlookupmodule(NULL, &oracle_lookup_module_info);
557 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
558 addlookupmodule(NULL, &passwd_lookup_module_info);
561 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
562 addlookupmodule(NULL, &pgsql_lookup_module_info);
565 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
566 addlookupmodule(NULL, &redis_lookup_module_info);
570 addlookupmodule(NULL, &lmdb_lookup_module_info);
574 addlookupmodule(NULL, &spf_lookup_module_info);
577 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
578 addlookupmodule(NULL, &sqlite_lookup_module_info);
581 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
582 addlookupmodule(NULL, &testdb_lookup_module_info);
585 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
586 addlookupmodule(NULL, &whoson_lookup_module_info);
589 /* This is a custom expansion, and not available as either
590 a list-syntax lookup or a lookup expansion. However, it is
591 implemented by a lookup module. */
593 addlookupmodule(NULL, &readsock_lookup_module_info);
595 #ifdef LOOKUP_MODULE_DIR
596 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
598 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
599 log_write(0, LOG_MAIN|LOG_PANIC,
600 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
604 const pcre2_code * regex_islookupmod = regex_must_compile(
605 US"_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
607 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
608 while ((ent = readdir(dd)))
610 char * name = ent->d_name;
611 int len = (int)strlen(name);
612 if (regex_match(regex_islookupmod, US name, len, NULL))
614 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
616 struct lookup_module_info *info;
617 const char *errormsg;
619 /* SRH: am I being paranoid here or what? */
620 if (pathnamelen > big_buffer_size)
622 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
623 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
627 /* SRH: snprintf here? */
628 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
630 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
632 errormsg = dlerror();
633 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
634 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
639 /* FreeBSD nsdispatch() can trigger dlerror() errors about
640 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
641 state before calling dlsym(), so that any error afterwards only comes
644 errormsg = dlerror();
646 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
647 if ((errormsg = dlerror()))
649 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
650 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
655 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
657 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
658 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
664 addlookupmodule(dl, info);
665 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
669 store_free((void*)regex_islookupmod);
673 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
676 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
678 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
679 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
681 /* now add all lookups to the real list */
682 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
683 for (int j = 0; j < p->info->lookupcount; j++)
684 add_lookup_to_list(p->info->lookups[j]);
685 store_reset(reset_point);
686 /* just to be sure */
687 lookupmodules = NULL;
690 #endif /*!MACRO_PREDEF*/
691 /* End of drtables.c */