1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2016 */
6 /* See the file NOTICE for conditions of use and distribution. */
13 /* This module contains tables that define the lookup methods and drivers
14 that are actually included in the binary. Its contents are controlled by
15 various macros in config.h that ultimately come from Local/Makefile. They are
16 all described in src/EDITME. */
19 lookup_info **lookup_list;
20 int lookup_list_count = 0;
22 /* Table of information about all possible authentication mechanisms. All
23 entries are always present if any mechanism is declared, but the functions are
24 set to NULL for those that are not compiled into the binary. */
27 #include "auths/cram_md5.h"
30 #ifdef AUTH_CYRUS_SASL
31 #include "auths/cyrus_sasl.h"
35 #include "auths/dovecot.h"
39 #include "auths/gsasl_exim.h"
42 #ifdef AUTH_HEIMDAL_GSSAPI
43 #include "auths/heimdal_gssapi.h"
47 #include "auths/plaintext.h"
51 #include "auths/spa.h"
55 #include "auths/tls.h"
58 auth_info auths_available[] = {
60 /* Checking by an expansion condition on plain text */
64 .driver_name = US"cram_md5", /* lookup name */
65 .options = auth_cram_md5_options,
66 .options_count = &auth_cram_md5_options_count,
67 .options_block = &auth_cram_md5_option_defaults,
68 .options_len = sizeof(auth_cram_md5_options_block),
69 .init = auth_cram_md5_init,
70 .servercode = auth_cram_md5_server,
71 .clientcode = auth_cram_md5_client,
72 .version_report = NULL
76 #ifdef AUTH_CYRUS_SASL
78 .driver_name = US"cyrus_sasl",
79 .options = auth_cyrus_sasl_options,
80 .options_count = &auth_cyrus_sasl_options_count,
81 .options_block = &auth_cyrus_sasl_option_defaults,
82 .options_len = sizeof(auth_cyrus_sasl_options_block),
83 .init = auth_cyrus_sasl_init,
84 .servercode = auth_cyrus_sasl_server,
86 .version_report = auth_cyrus_sasl_version_report
92 .driver_name = US"dovecot",
93 .options = auth_dovecot_options,
94 .options_count = &auth_dovecot_options_count,
95 .options_block = &auth_dovecot_option_defaults,
96 .options_len = sizeof(auth_dovecot_options_block),
97 .init = auth_dovecot_init,
98 .servercode = auth_dovecot_server,
100 .version_report = NULL
106 .driver_name = US"gsasl",
107 .options = auth_gsasl_options,
108 .options_count = &auth_gsasl_options_count,
109 .options_block = &auth_gsasl_option_defaults,
110 .options_len = sizeof(auth_gsasl_options_block),
111 .init = auth_gsasl_init,
112 .servercode = auth_gsasl_server,
114 .version_report = auth_gsasl_version_report
118 #ifdef AUTH_HEIMDAL_GSSAPI
120 .driver_name = US"heimdal_gssapi",
121 .options = auth_heimdal_gssapi_options,
122 .options_count &auth_heimdal_gssapi_options_count,
123 .options_block = &auth_heimdal_gssapi_option_defaults,
124 .options_len = sizeof(auth_heimdal_gssapi_options_block),
125 .init = auth_heimdal_gssapi_init,
126 .servercode = auth_heimdal_gssapi_server,
128 .version_report = auth_heimdal_gssapi_version_report
132 #ifdef AUTH_PLAINTEXT
134 .driver_name = US"plaintext",
135 .options = auth_plaintext_options,
136 .options_count = &auth_plaintext_options_count,
137 .options_block = &auth_plaintext_option_defaults,
138 .options_len = sizeof(auth_plaintext_options_block),
139 .init = auth_plaintext_init,
140 .servercode = auth_plaintext_server,
141 .clientcode = auth_plaintext_client,
142 .version_report = NULL
148 .driver_name = US"spa",
149 .options = auth_spa_options,
150 .options_count = &auth_spa_options_count,
151 .options_block = &auth_spa_option_defaults,
152 .options_len = sizeof(auth_spa_options_block),
153 .init = auth_spa_init,
154 .servercode = auth_spa_server,
155 .clientcode = auth_spa_client,
156 .version_report = NULL
162 .driver_name = US"tls",
163 .options = auth_tls_options,
164 .options_count = &auth_tls_options_count,
165 .options_block = &auth_tls_option_defaults,
166 .options_len = sizeof(auth_tls_options_block),
167 .init = auth_tls_init,
168 .servercode = auth_tls_server,
170 .version_report = NULL
174 { .driver_name = US"" } /* end marker */
178 /* Tables of information about which routers and transports are included in the
181 /* Pull in the necessary header files */
183 #include "routers/rf_functions.h"
186 #include "routers/accept.h"
189 #ifdef ROUTER_DNSLOOKUP
190 #include "routers/dnslookup.h"
193 #ifdef ROUTER_MANUALROUTE
194 #include "routers/manualroute.h"
197 #ifdef ROUTER_IPLITERAL
198 #include "routers/ipliteral.h"
201 #ifdef ROUTER_IPLOOKUP
202 #include "routers/iplookup.h"
205 #ifdef ROUTER_QUERYPROGRAM
206 #include "routers/queryprogram.h"
209 #ifdef ROUTER_REDIRECT
210 #include "routers/redirect.h"
213 #ifdef TRANSPORT_APPENDFILE
214 #include "transports/appendfile.h"
217 #ifdef TRANSPORT_AUTOREPLY
218 #include "transports/autoreply.h"
221 #ifdef TRANSPORT_LMTP
222 #include "transports/lmtp.h"
225 #ifdef TRANSPORT_PIPE
226 #include "transports/pipe.h"
229 #ifdef EXPERIMENTAL_QUEUEFILE
230 #include "transports/queuefile.h"
233 #ifdef TRANSPORT_SMTP
234 #include "transports/smtp.h"
238 /* Now set up the structures, terminated by an entry with a null name. */
240 router_info routers_available[] = {
243 .driver_name = US"accept",
244 .options = accept_router_options,
245 .options_count = &accept_router_options_count,
246 .options_block = &accept_router_option_defaults,
247 .options_len = sizeof(accept_router_options_block),
248 .init = accept_router_init,
249 .code = accept_router_entry,
250 .tidyup = NULL, /* no tidyup entry */
251 .ri_flags = ri_yestransport
254 #ifdef ROUTER_DNSLOOKUP
256 .driver_name = US"dnslookup",
257 .options = dnslookup_router_options,
258 .options_count = &dnslookup_router_options_count,
259 .options_block = &dnslookup_router_option_defaults,
260 .options_len = sizeof(dnslookup_router_options_block),
261 .init = dnslookup_router_init,
262 .code = dnslookup_router_entry,
263 .tidyup = NULL, /* no tidyup entry */
264 .ri_flags = ri_yestransport
267 #ifdef ROUTER_IPLITERAL
269 .driver_name = US"ipliteral",
270 .options = ipliteral_router_options,
271 .options_count = &ipliteral_router_options_count,
272 .options_block = &ipliteral_router_option_defaults,
273 .options_len = sizeof(ipliteral_router_options_block),
274 .init = ipliteral_router_init,
275 .code = ipliteral_router_entry,
276 .tidyup = NULL, /* no tidyup entry */
277 .ri_flags = ri_yestransport
280 #ifdef ROUTER_IPLOOKUP
282 .driver_name = US"iplookup",
283 .options = iplookup_router_options,
284 .options_count = &iplookup_router_options_count,
285 .options_block = &iplookup_router_option_defaults,
286 .options_len = sizeof(iplookup_router_options_block),
287 .init = iplookup_router_init,
288 .code = iplookup_router_entry,
289 .tidyup = NULL, /* no tidyup entry */
290 .ri_flags = ri_notransport
293 #ifdef ROUTER_MANUALROUTE
295 .driver_name = US"manualroute",
296 .options = manualroute_router_options,
297 .options_count = &manualroute_router_options_count,
298 .options_block = &manualroute_router_option_defaults,
299 .options_len = sizeof(manualroute_router_options_block),
300 .init = manualroute_router_init,
301 .code = manualroute_router_entry,
302 .tidyup = NULL, /* no tidyup entry */
306 #ifdef ROUTER_QUERYPROGRAM
308 .driver_name = US"queryprogram",
309 .options = queryprogram_router_options,
310 .options_count = &queryprogram_router_options_count,
311 .options_block = &queryprogram_router_option_defaults,
312 .options_len = sizeof(queryprogram_router_options_block),
313 .init = queryprogram_router_init,
314 .code = queryprogram_router_entry,
315 .tidyup = NULL, /* no tidyup entry */
319 #ifdef ROUTER_REDIRECT
321 .driver_name = US"redirect",
322 .options = redirect_router_options,
323 .options_count = &redirect_router_options_count,
324 .options_block = &redirect_router_option_defaults,
325 .options_len = sizeof(redirect_router_options_block),
326 .init = redirect_router_init,
327 .code = redirect_router_entry,
328 .tidyup = NULL, /* no tidyup entry */
329 .ri_flags = ri_notransport
337 transport_info transports_available[] = {
338 #ifdef TRANSPORT_APPENDFILE
340 .driver_name = US"appendfile",
341 .options = appendfile_transport_options,
342 .options_count = &appendfile_transport_options_count,
343 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
344 .options_len = sizeof(appendfile_transport_options_block),
345 .init = appendfile_transport_init,
346 .code = appendfile_transport_entry,
352 #ifdef TRANSPORT_AUTOREPLY
354 .driver_name = US"autoreply",
355 .options = autoreply_transport_options,
356 .options_count = &autoreply_transport_options_count,
357 .options_block = &autoreply_transport_option_defaults,
358 .options_len = sizeof(autoreply_transport_options_block),
359 .init = autoreply_transport_init,
360 .code = autoreply_transport_entry,
366 #ifdef TRANSPORT_LMTP
368 .driver_name = US"lmtp",
369 .options = lmtp_transport_options,
370 .options_count = &lmtp_transport_options_count,
371 .options_block = &lmtp_transport_option_defaults,
372 .options_len = sizeof(lmtp_transport_options_block),
373 .init = lmtp_transport_init,
374 .code = lmtp_transport_entry,
380 #ifdef TRANSPORT_PIPE
382 .driver_name = US"pipe",
383 .options = pipe_transport_options,
384 .options_count = &pipe_transport_options_count,
385 .options_block = &pipe_transport_option_defaults,
386 .options_len = sizeof(pipe_transport_options_block),
387 .init = pipe_transport_init,
388 .code = pipe_transport_entry,
394 #ifdef EXPERIMENTAL_QUEUEFILE
396 .driver_name = US"queuefile",
397 .options = queuefile_transport_options,
398 .options_count = &queuefile_transport_options_count,
399 .options_block = &queuefile_transport_option_defaults,
400 .options_len = sizeof(queuefile_transport_options_block),
401 .init = queuefile_transport_init,
402 .code = queuefile_transport_entry,
408 #ifdef TRANSPORT_SMTP
410 .driver_name = US"smtp",
411 .options = smtp_transport_options,
412 .options_count = &smtp_transport_options_count,
413 .options_block = &smtp_transport_option_defaults,
414 .options_len = sizeof(smtp_transport_options_block),
415 .init = smtp_transport_init,
416 .code = smtp_transport_entry,
418 .closedown = smtp_transport_closedown,
428 struct lookupmodulestr
431 struct lookup_module_info *info;
432 struct lookupmodulestr *next;
435 static struct lookupmodulestr *lookupmodules = NULL;
438 addlookupmodule(void *dl, struct lookup_module_info *info)
440 struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
444 p->next = lookupmodules;
446 lookup_list_count += info->lookupcount;
449 /* only valid after lookup_list and lookup_list_count are assigned */
451 add_lookup_to_list(lookup_info *info)
453 /* need to add the lookup to lookup_list, sorted */
456 /* strategy is to go through the list until we find
457 either an empty spot or a name that is higher.
458 this can't fail because we have enough space. */
460 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
463 if (lookup_list[pos])
465 /* need to insert it, so move all the other items up
466 (last slot is still empty, of course) */
468 memmove(&lookup_list[pos+1],
470 sizeof(lookup_info *) * (lookup_list_count-pos-1));
472 lookup_list[pos] = info;
476 /* These need to be at file level for old versions of gcc (2.95.2 reported),
477 * which give parse errors on an extern in function scope. Each entry needs
478 * to also be invoked in init_lookup_list() below */
480 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
481 extern lookup_module_info cdb_lookup_module_info;
483 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
484 extern lookup_module_info dbmdb_lookup_module_info;
486 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
487 extern lookup_module_info dnsdb_lookup_module_info;
489 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
490 extern lookup_module_info dsearch_lookup_module_info;
492 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
493 extern lookup_module_info ibase_lookup_module_info;
495 #if defined(LOOKUP_LDAP)
496 extern lookup_module_info ldap_lookup_module_info;
498 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
499 extern lookup_module_info lsearch_lookup_module_info;
501 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
502 extern lookup_module_info mysql_lookup_module_info;
504 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
505 extern lookup_module_info nis_lookup_module_info;
507 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
508 extern lookup_module_info nisplus_lookup_module_info;
510 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
511 extern lookup_module_info oracle_lookup_module_info;
513 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
514 extern lookup_module_info passwd_lookup_module_info;
516 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
517 extern lookup_module_info pgsql_lookup_module_info;
519 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
520 extern lookup_module_info redis_lookup_module_info;
522 #if defined(EXPERIMENTAL_LMDB)
523 extern lookup_module_info lmdb_lookup_module_info;
525 #if defined(EXPERIMENTAL_SPF)
526 extern lookup_module_info spf_lookup_module_info;
528 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
529 extern lookup_module_info sqlite_lookup_module_info;
531 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
532 extern lookup_module_info testdb_lookup_module_info;
534 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
535 extern lookup_module_info whoson_lookup_module_info;
540 init_lookup_list(void)
542 #ifdef LOOKUP_MODULE_DIR
545 int countmodules = 0;
546 int moduleerrors = 0;
548 struct lookupmodulestr *p;
549 static BOOL lookup_list_init_done = FALSE;
552 if (lookup_list_init_done)
554 lookup_list_init_done = TRUE;
556 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
557 addlookupmodule(NULL, &cdb_lookup_module_info);
560 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
561 addlookupmodule(NULL, &dbmdb_lookup_module_info);
564 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
565 addlookupmodule(NULL, &dnsdb_lookup_module_info);
568 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
569 addlookupmodule(NULL, &dsearch_lookup_module_info);
572 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
573 addlookupmodule(NULL, &ibase_lookup_module_info);
577 addlookupmodule(NULL, &ldap_lookup_module_info);
580 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
581 addlookupmodule(NULL, &lsearch_lookup_module_info);
584 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
585 addlookupmodule(NULL, &mysql_lookup_module_info);
588 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
589 addlookupmodule(NULL, &nis_lookup_module_info);
592 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
593 addlookupmodule(NULL, &nisplus_lookup_module_info);
596 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
597 addlookupmodule(NULL, &oracle_lookup_module_info);
600 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
601 addlookupmodule(NULL, &passwd_lookup_module_info);
604 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
605 addlookupmodule(NULL, &pgsql_lookup_module_info);
608 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
609 addlookupmodule(NULL, &redis_lookup_module_info);
612 #ifdef EXPERIMENTAL_LMDB
613 addlookupmodule(NULL, &lmdb_lookup_module_info);
616 #ifdef EXPERIMENTAL_SPF
617 addlookupmodule(NULL, &spf_lookup_module_info);
620 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
621 addlookupmodule(NULL, &sqlite_lookup_module_info);
624 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
625 addlookupmodule(NULL, &testdb_lookup_module_info);
628 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
629 addlookupmodule(NULL, &whoson_lookup_module_info);
632 #ifdef LOOKUP_MODULE_DIR
633 dd = opendir(LOOKUP_MODULE_DIR);
635 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
636 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
639 const pcre *regex_islookupmod = regex_must_compile(
640 US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
642 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
643 while ((ent = readdir(dd)) != NULL) {
644 char *name = ent->d_name;
645 int len = (int)strlen(name);
646 if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
647 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
649 struct lookup_module_info *info;
650 const char *errormsg;
652 /* SRH: am I being paranoid here or what? */
653 if (pathnamelen > big_buffer_size) {
654 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
655 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
659 /* SRH: snprintf here? */
660 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
662 dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
664 fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
666 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
670 /* FreeBSD nsdispatch() can trigger dlerror() errors about
671 * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
672 * state before calling dlsym(), so that any error afterwards only
673 * comes from dlsym().
675 errormsg = dlerror();
677 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
678 if ((errormsg = dlerror()) != NULL) {
679 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
682 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
685 if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
686 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
689 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
693 addlookupmodule(dl, info);
694 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
698 store_free((void*)regex_islookupmod);
702 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
705 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
707 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
708 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
710 /* now add all lookups to the real list */
714 struct lookupmodulestr *pnext;
716 for (j = 0; j < p->info->lookupcount; j++)
717 add_lookup_to_list(p->info->lookups[j]);
723 /* just to be sure */
724 lookupmodules = NULL;
727 #endif /*!MACRO_PREDEF*/
728 /* End of drtables.c */