1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4 
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 
9 
10 #include "exim.h"
11 
12 #include <string.h>
13 
14 /* This module contains tables that define the lookup methods and drivers
15 that are actually included in the binary. Its contents are controlled by
16 various macros in config.h that ultimately come from Local/Makefile. They are
17 all described in src/EDITME. */
18 
19 
20 lookup_info **lookup_list;
21 int lookup_list_count = 0;
22 
23 /* Table of information about all possible authentication mechanisms. All
24 entries are always present if any mechanism is declared, but the functions are
25 set to NULL for those that are not compiled into the binary. */
26 
27 #ifdef AUTH_CRAM_MD5
28 #include "auths/cram_md5.h"
29 #endif
30 
31 #ifdef AUTH_CYRUS_SASL
32 #include "auths/cyrus_sasl.h"
33 #endif
34 
35 #ifdef AUTH_DOVECOT
36 #include "auths/dovecot.h"
37 #endif
38 
39 #ifdef AUTH_EXTERNAL
40 #include "auths/external.h"
41 #endif
42 
43 #ifdef AUTH_GSASL
44 #include "auths/gsasl_exim.h"
45 #endif
46 
47 #ifdef AUTH_HEIMDAL_GSSAPI
48 #include "auths/heimdal_gssapi.h"
49 #endif
50 
51 #ifdef AUTH_PLAINTEXT
52 #include "auths/plaintext.h"
53 #endif
54 
55 #ifdef AUTH_SPA
56 #include "auths/spa.h"
57 #endif
58 
59 #ifdef AUTH_TLS
60 #include "auths/tls.h"
61 #endif
62 
63 auth_info auths_available[] = {
64 
65 /* Checking by an expansion condition on plain text */
66 
67 #ifdef AUTH_CRAM_MD5
68   {
69   .driver_name =	US"cram_md5",                              /* lookup name */
70   .options =		auth_cram_md5_options,
71   .options_count =	&auth_cram_md5_options_count,
72   .options_block =	&auth_cram_md5_option_defaults,
73   .options_len =	sizeof(auth_cram_md5_options_block),
74   .init =		auth_cram_md5_init,
75   .servercode =		auth_cram_md5_server,
76   .clientcode =		auth_cram_md5_client,
77   .version_report =	NULL,
78   .macros_create =	NULL,
79   },
80 #endif
81 
82 #ifdef AUTH_CYRUS_SASL
83   {
84   .driver_name =	US"cyrus_sasl",
85   .options =		auth_cyrus_sasl_options,
86   .options_count =	&auth_cyrus_sasl_options_count,
87   .options_block =	&auth_cyrus_sasl_option_defaults,
88   .options_len =	sizeof(auth_cyrus_sasl_options_block),
89   .init =		auth_cyrus_sasl_init,
90   .servercode =		auth_cyrus_sasl_server,
91   .clientcode =		NULL,
92   .version_report =	auth_cyrus_sasl_version_report,
93   .macros_create =	NULL,
94   },
95 #endif
96 
97 #ifdef AUTH_DOVECOT
98   {
99   .driver_name =	US"dovecot",
100   .options =		auth_dovecot_options,
101   .options_count =	&auth_dovecot_options_count,
102   .options_block =	&auth_dovecot_option_defaults,
103   .options_len =	sizeof(auth_dovecot_options_block),
104   .init =		auth_dovecot_init,
105   .servercode =		auth_dovecot_server,
106   .clientcode =		NULL,
107   .version_report =	NULL,
108   .macros_create =	NULL,
109   },
110 #endif
111 
112 #ifdef AUTH_EXTERNAL
113   {
114   .driver_name =	US"external",
115   .options =		auth_external_options,
116   .options_count =	&auth_external_options_count,
117   .options_block =	&auth_external_option_defaults,
118   .options_len =	sizeof(auth_external_options_block),
119   .init =		auth_external_init,
120   .servercode =		auth_external_server,
121   .clientcode =		auth_external_client,
122   .version_report =	NULL,
123   .macros_create =	NULL,
124   },
125 #endif
126 
127 #ifdef AUTH_GSASL
128   {
129   .driver_name =	US"gsasl",
130   .options =		auth_gsasl_options,
131   .options_count =	&auth_gsasl_options_count,
132   .options_block =	&auth_gsasl_option_defaults,
133   .options_len =	sizeof(auth_gsasl_options_block),
134   .init =		auth_gsasl_init,
135   .servercode =		auth_gsasl_server,
136   .clientcode =		auth_gsasl_client,
137   .version_report =	auth_gsasl_version_report,
138   .macros_create =	auth_gsasl_macros,
139   },
140 #endif
141 
142 #ifdef AUTH_HEIMDAL_GSSAPI
143   {
144   .driver_name =	US"heimdal_gssapi",
145   .options =		auth_heimdal_gssapi_options,
146   .options_count =	&auth_heimdal_gssapi_options_count,
147   .options_block =	&auth_heimdal_gssapi_option_defaults,
148   .options_len =	sizeof(auth_heimdal_gssapi_options_block),
149   .init =		auth_heimdal_gssapi_init,
150   .servercode =		auth_heimdal_gssapi_server,
151   .clientcode =		NULL,
152   .version_report =	auth_heimdal_gssapi_version_report,
153   .macros_create =	NULL,
154   },
155 #endif
156 
157 #ifdef AUTH_PLAINTEXT
158   {
159   .driver_name =	US"plaintext",
160   .options =		auth_plaintext_options,
161   .options_count =	&auth_plaintext_options_count,
162   .options_block =	&auth_plaintext_option_defaults,
163   .options_len =	sizeof(auth_plaintext_options_block),
164   .init =		auth_plaintext_init,
165   .servercode =		auth_plaintext_server,
166   .clientcode =		auth_plaintext_client,
167   .version_report =	NULL,
168   .macros_create =	NULL,
169   },
170 #endif
171 
172 #ifdef AUTH_SPA
173   {
174   .driver_name =	US"spa",
175   .options =		auth_spa_options,
176   .options_count =	&auth_spa_options_count,
177   .options_block =	&auth_spa_option_defaults,
178   .options_len =	sizeof(auth_spa_options_block),
179   .init =		auth_spa_init,
180   .servercode =		auth_spa_server,
181   .clientcode =		auth_spa_client,
182   .version_report =	NULL,
183   .macros_create =	NULL,
184   },
185 #endif
186 
187 #ifdef AUTH_TLS
188   {
189   .driver_name =	US"tls",
190   .options =		auth_tls_options,
191   .options_count =	&auth_tls_options_count,
192   .options_block =	&auth_tls_option_defaults,
193   .options_len =	sizeof(auth_tls_options_block),
194   .init =		auth_tls_init,
195   .servercode =		auth_tls_server,
196   .clientcode =		NULL,
197   .version_report =	NULL,
198   .macros_create =	NULL,
199   },
200 #endif
201 
202   { .driver_name = US"" }		/* end marker */
203 };
204 
205 
206 /* Tables of information about which routers and transports are included in the
207 exim binary. */
208 
209 /* Pull in the necessary header files */
210 
211 #include "routers/rf_functions.h"
212 
213 #ifdef ROUTER_ACCEPT
214 #include "routers/accept.h"
215 #endif
216 
217 #ifdef ROUTER_DNSLOOKUP
218 #include "routers/dnslookup.h"
219 #endif
220 
221 #ifdef ROUTER_MANUALROUTE
222 #include "routers/manualroute.h"
223 #endif
224 
225 #ifdef ROUTER_IPLITERAL
226 #include "routers/ipliteral.h"
227 #endif
228 
229 #ifdef ROUTER_IPLOOKUP
230 #include "routers/iplookup.h"
231 #endif
232 
233 #ifdef ROUTER_QUERYPROGRAM
234 #include "routers/queryprogram.h"
235 #endif
236 
237 #ifdef ROUTER_REDIRECT
238 #include "routers/redirect.h"
239 #endif
240 
241 #ifdef TRANSPORT_APPENDFILE
242 #include "transports/appendfile.h"
243 #endif
244 
245 #ifdef TRANSPORT_AUTOREPLY
246 #include "transports/autoreply.h"
247 #endif
248 
249 #ifdef TRANSPORT_LMTP
250 #include "transports/lmtp.h"
251 #endif
252 
253 #ifdef TRANSPORT_PIPE
254 #include "transports/pipe.h"
255 #endif
256 
257 #ifdef EXPERIMENTAL_QUEUEFILE
258 #include "transports/queuefile.h"
259 #endif
260 
261 #ifdef TRANSPORT_SMTP
262 #include "transports/smtp.h"
263 #endif
264 
265 
266 /* Now set up the structures, terminated by an entry with a null name. */
267 
268 router_info routers_available[] = {
269 #ifdef ROUTER_ACCEPT
270   {
271   .driver_name =	US"accept",
272   .options =		accept_router_options,
273   .options_count =	&accept_router_options_count,
274   .options_block =	&accept_router_option_defaults,
275   .options_len =	sizeof(accept_router_options_block),
276   .init =		accept_router_init,
277   .code =		accept_router_entry,
278   .tidyup =		NULL,     /* no tidyup entry */
279   .ri_flags =		ri_yestransport
280   },
281 #endif
282 #ifdef ROUTER_DNSLOOKUP
283   {
284   .driver_name =	US"dnslookup",
285   .options =		dnslookup_router_options,
286   .options_count =	&dnslookup_router_options_count,
287   .options_block =	&dnslookup_router_option_defaults,
288   .options_len =	sizeof(dnslookup_router_options_block),
289   .init =		dnslookup_router_init,
290   .code =		dnslookup_router_entry,
291   .tidyup =		NULL,     /* no tidyup entry */
292   .ri_flags =		ri_yestransport
293   },
294 #endif
295 #ifdef ROUTER_IPLITERAL
296   {
297   .driver_name =	US"ipliteral",
298   .options =		ipliteral_router_options,
299   .options_count =	&ipliteral_router_options_count,
300   .options_block =	&ipliteral_router_option_defaults,
301   .options_len =	sizeof(ipliteral_router_options_block),
302   .init =		ipliteral_router_init,
303   .code =		ipliteral_router_entry,
304   .tidyup =		NULL,     /* no tidyup entry */
305   .ri_flags =		ri_yestransport
306   },
307 #endif
308 #ifdef ROUTER_IPLOOKUP
309   {
310   .driver_name =	US"iplookup",
311   .options =		iplookup_router_options,
312   .options_count =	&iplookup_router_options_count,
313   .options_block =	&iplookup_router_option_defaults,
314   .options_len =	sizeof(iplookup_router_options_block),
315   .init =		iplookup_router_init,
316   .code =		iplookup_router_entry,
317   .tidyup =		NULL,     /* no tidyup entry */
318   .ri_flags =		ri_notransport
319   },
320 #endif
321 #ifdef ROUTER_MANUALROUTE
322   {
323   .driver_name =	US"manualroute",
324   .options =		manualroute_router_options,
325   .options_count =	&manualroute_router_options_count,
326   .options_block =	&manualroute_router_option_defaults,
327   .options_len =	sizeof(manualroute_router_options_block),
328   .init =		manualroute_router_init,
329   .code =		manualroute_router_entry,
330   .tidyup =		NULL,     /* no tidyup entry */
331   .ri_flags =		0
332   },
333 #endif
334 #ifdef ROUTER_QUERYPROGRAM
335   {
336   .driver_name =	US"queryprogram",
337   .options =		queryprogram_router_options,
338   .options_count =	&queryprogram_router_options_count,
339   .options_block =	&queryprogram_router_option_defaults,
340   .options_len =	sizeof(queryprogram_router_options_block),
341   .init =		queryprogram_router_init,
342   .code =		queryprogram_router_entry,
343   .tidyup =		NULL,     /* no tidyup entry */
344   .ri_flags =		0
345   },
346 #endif
347 #ifdef ROUTER_REDIRECT
348   {
349   .driver_name =	US"redirect",
350   .options =		redirect_router_options,
351   .options_count =	&redirect_router_options_count,
352   .options_block =	&redirect_router_option_defaults,
353   .options_len =	sizeof(redirect_router_options_block),
354   .init =		redirect_router_init,
355   .code =		redirect_router_entry,
356   .tidyup =		NULL,     /* no tidyup entry */
357   .ri_flags =		ri_notransport
358   },
359 #endif
360   { US"" }
361 };
362 
363 
364 
365 transport_info transports_available[] = {
366 #ifdef TRANSPORT_APPENDFILE
367   {
368   .driver_name =	US"appendfile",
369   .options =		appendfile_transport_options,
370   .options_count =	&appendfile_transport_options_count,
371   .options_block =	&appendfile_transport_option_defaults,       /* private options defaults */
372   .options_len =	sizeof(appendfile_transport_options_block),
373   .init =		appendfile_transport_init,
374   .code =		appendfile_transport_entry,
375   .tidyup =		NULL,
376   .closedown =		NULL,
377   .local =		TRUE
378   },
379 #endif
380 #ifdef TRANSPORT_AUTOREPLY
381   {
382   .driver_name =	US"autoreply",
383   .options =		autoreply_transport_options,
384   .options_count =	&autoreply_transport_options_count,
385   .options_block =	&autoreply_transport_option_defaults,
386   .options_len =	sizeof(autoreply_transport_options_block),
387   .init =		autoreply_transport_init,
388   .code =		autoreply_transport_entry,
389   .tidyup =		NULL,
390   .closedown =		NULL,
391   .local =		TRUE
392   },
393 #endif
394 #ifdef TRANSPORT_LMTP
395   {
396   .driver_name =	US"lmtp",
397   .options =		lmtp_transport_options,
398   .options_count =	&lmtp_transport_options_count,
399   .options_block =	&lmtp_transport_option_defaults,
400   .options_len =	sizeof(lmtp_transport_options_block),
401   .init =		lmtp_transport_init,
402   .code =		lmtp_transport_entry,
403   .tidyup =		NULL,
404   .closedown =		NULL,
405   .local =		TRUE
406   },
407 #endif
408 #ifdef TRANSPORT_PIPE
409   {
410   .driver_name =	US"pipe",
411   .options =		pipe_transport_options,
412   .options_count =	&pipe_transport_options_count,
413   .options_block =	&pipe_transport_option_defaults,
414   .options_len =	sizeof(pipe_transport_options_block),
415   .init =		pipe_transport_init,
416   .code =		pipe_transport_entry,
417   .tidyup =		NULL,
418   .closedown =		NULL,
419   .local =		TRUE
420   },
421 #endif
422 #ifdef EXPERIMENTAL_QUEUEFILE
423   {
424   .driver_name =	US"queuefile",
425   .options =		queuefile_transport_options,
426   .options_count =	&queuefile_transport_options_count,
427   .options_block =	&queuefile_transport_option_defaults,
428   .options_len =	sizeof(queuefile_transport_options_block),
429   .init =		queuefile_transport_init,
430   .code =		queuefile_transport_entry,
431   .tidyup =		NULL,
432   .closedown =		NULL,
433   .local =		TRUE
434   },
435 #endif
436 #ifdef TRANSPORT_SMTP
437   {
438   .driver_name =	US"smtp",
439   .options =		smtp_transport_options,
440   .options_count =	&smtp_transport_options_count,
441   .options_block =	&smtp_transport_option_defaults,
442   .options_len =	sizeof(smtp_transport_options_block),
443   .init =		smtp_transport_init,
444   .code =		smtp_transport_entry,
445   .tidyup =		NULL,
446   .closedown =		smtp_transport_closedown,
447   .local =		FALSE
448   },
449 #endif
450   { US"" }
451 };
452 
453 #ifndef MACRO_PREDEF
454 
455 gstring *
auth_show_supported(gstring * g)456 auth_show_supported(gstring * g)
457 {
458 g = string_cat(g, US"Authenticators:");
459 for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
460        	g = string_fmt_append(g, " %s", ai->driver_name);
461 return string_cat(g, US"\n");
462 }
463 
464 gstring *
route_show_supported(gstring * g)465 route_show_supported(gstring * g)
466 {
467 g = string_cat(g, US"Routers:");
468 for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
469        	g = string_fmt_append(g, " %s", rr->driver_name);
470 return string_cat(g, US"\n");
471 }
472 
473 gstring *
transport_show_supported(gstring * g)474 transport_show_supported(gstring * g)
475 {
476 g = string_cat(g, US"Transports:");
477 #ifdef TRANSPORT_APPENDFILE
478   g = string_cat(g, US" appendfile");
479   #ifdef SUPPORT_MAILDIR
480     g = string_cat(g, US"/maildir");	/* damn these subclasses */
481   #endif
482   #ifdef SUPPORT_MAILSTORE
483     g = string_cat(g, US"/mailstore");
484   #endif
485   #ifdef SUPPORT_MBX
486     g = string_cat(g, US"/mbx");
487   #endif
488 #endif
489 #ifdef TRANSPORT_AUTOREPLY
490   g = string_cat(g, US" autoreply");
491 #endif
492 #ifdef TRANSPORT_LMTP
493   g = string_cat(g, US" lmtp");
494 #endif
495 #ifdef TRANSPORT_PIPE
496   g = string_cat(g, US" pipe");
497 #endif
498 #ifdef EXPERIMENTAL_QUEUEFILE
499   g = string_cat(g, US" queuefile");
500 #endif
501 #ifdef TRANSPORT_SMTP
502   g = string_cat(g, US" smtp");
503 #endif
504 return string_cat(g, US"\n");
505 }
506 
507 
508 
509 struct lookupmodulestr
510 {
511   void *dl;
512   struct lookup_module_info *info;
513   struct lookupmodulestr *next;
514 };
515 
516 static struct lookupmodulestr *lookupmodules = NULL;
517 
518 static void
addlookupmodule(void * dl,struct lookup_module_info * info)519 addlookupmodule(void *dl, struct lookup_module_info *info)
520 {
521 struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
522 
523 p->dl = dl;
524 p->info = info;
525 p->next = lookupmodules;
526 lookupmodules = p;
527 lookup_list_count += info->lookupcount;
528 }
529 
530 /* only valid after lookup_list and lookup_list_count are assigned */
531 static void
add_lookup_to_list(lookup_info * info)532 add_lookup_to_list(lookup_info *info)
533 {
534 /* need to add the lookup to lookup_list, sorted */
535 int pos = 0;
536 
537 /* strategy is to go through the list until we find
538 either an empty spot or a name that is higher.
539 this can't fail because we have enough space. */
540 
541 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
542   pos++;
543 
544 if (lookup_list[pos])
545   {
546   /* need to insert it, so move all the other items up
547   (last slot is still empty, of course) */
548 
549   memmove(&lookup_list[pos+1], &lookup_list[pos],
550 	  sizeof(lookup_info *) * (lookup_list_count-pos-1));
551   }
552 lookup_list[pos] = info;
553 }
554 
555 
556 /* These need to be at file level for old versions of gcc (2.95.2 reported),
557  * which give parse errors on an extern in function scope.  Each entry needs
558  * to also be invoked in init_lookup_list() below  */
559 
560 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
561 extern lookup_module_info cdb_lookup_module_info;
562 #endif
563 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
564 extern lookup_module_info dbmdb_lookup_module_info;
565 #endif
566 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
567 extern lookup_module_info dnsdb_lookup_module_info;
568 #endif
569 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
570 extern lookup_module_info dsearch_lookup_module_info;
571 #endif
572 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
573 extern lookup_module_info ibase_lookup_module_info;
574 #endif
575 #if defined(LOOKUP_JSON)
576 extern lookup_module_info json_lookup_module_info;
577 #endif
578 #if defined(LOOKUP_LDAP)
579 extern lookup_module_info ldap_lookup_module_info;
580 #endif
581 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
582 extern lookup_module_info lsearch_lookup_module_info;
583 #endif
584 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
585 extern lookup_module_info mysql_lookup_module_info;
586 #endif
587 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
588 extern lookup_module_info nis_lookup_module_info;
589 #endif
590 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
591 extern lookup_module_info nisplus_lookup_module_info;
592 #endif
593 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
594 extern lookup_module_info oracle_lookup_module_info;
595 #endif
596 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
597 extern lookup_module_info passwd_lookup_module_info;
598 #endif
599 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
600 extern lookup_module_info pgsql_lookup_module_info;
601 #endif
602 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
603 extern lookup_module_info redis_lookup_module_info;
604 #endif
605 #if defined(LOOKUP_LMDB)
606 extern lookup_module_info lmdb_lookup_module_info;
607 #endif
608 #if defined(SUPPORT_SPF)
609 extern lookup_module_info spf_lookup_module_info;
610 #endif
611 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
612 extern lookup_module_info sqlite_lookup_module_info;
613 #endif
614 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
615 extern lookup_module_info testdb_lookup_module_info;
616 #endif
617 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
618 extern lookup_module_info whoson_lookup_module_info;
619 #endif
620 
621 extern lookup_module_info readsock_lookup_module_info;
622 
623 
624 void
init_lookup_list(void)625 init_lookup_list(void)
626 {
627 #ifdef LOOKUP_MODULE_DIR
628 DIR *dd;
629 struct dirent *ent;
630 int countmodules = 0;
631 int moduleerrors = 0;
632 #endif
633 static BOOL lookup_list_init_done = FALSE;
634 rmark reset_point;
635 
636 if (lookup_list_init_done)
637   return;
638 reset_point = store_mark();
639 lookup_list_init_done = TRUE;
640 
641 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
642 addlookupmodule(NULL, &cdb_lookup_module_info);
643 #endif
644 
645 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
646 addlookupmodule(NULL, &dbmdb_lookup_module_info);
647 #endif
648 
649 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
650 addlookupmodule(NULL, &dnsdb_lookup_module_info);
651 #endif
652 
653 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
654 addlookupmodule(NULL, &dsearch_lookup_module_info);
655 #endif
656 
657 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
658 addlookupmodule(NULL, &ibase_lookup_module_info);
659 #endif
660 
661 #ifdef LOOKUP_LDAP
662 addlookupmodule(NULL, &ldap_lookup_module_info);
663 #endif
664 
665 #ifdef LOOKUP_JSON
666 addlookupmodule(NULL, &json_lookup_module_info);
667 #endif
668 
669 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
670 addlookupmodule(NULL, &lsearch_lookup_module_info);
671 #endif
672 
673 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
674 addlookupmodule(NULL, &mysql_lookup_module_info);
675 #endif
676 
677 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
678 addlookupmodule(NULL, &nis_lookup_module_info);
679 #endif
680 
681 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
682 addlookupmodule(NULL, &nisplus_lookup_module_info);
683 #endif
684 
685 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
686 addlookupmodule(NULL, &oracle_lookup_module_info);
687 #endif
688 
689 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
690 addlookupmodule(NULL, &passwd_lookup_module_info);
691 #endif
692 
693 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
694 addlookupmodule(NULL, &pgsql_lookup_module_info);
695 #endif
696 
697 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
698 addlookupmodule(NULL, &redis_lookup_module_info);
699 #endif
700 
701 #ifdef LOOKUP_LMDB
702 addlookupmodule(NULL, &lmdb_lookup_module_info);
703 #endif
704 
705 #ifdef SUPPORT_SPF
706 addlookupmodule(NULL, &spf_lookup_module_info);
707 #endif
708 
709 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
710 addlookupmodule(NULL, &sqlite_lookup_module_info);
711 #endif
712 
713 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
714 addlookupmodule(NULL, &testdb_lookup_module_info);
715 #endif
716 
717 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
718 addlookupmodule(NULL, &whoson_lookup_module_info);
719 #endif
720 
721 addlookupmodule(NULL, &readsock_lookup_module_info);
722 
723 #ifdef LOOKUP_MODULE_DIR
724 if (!(dd = exim_opendir(LOOKUP_MODULE_DIR)))
725   {
726   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
727   log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
728   }
729 else
730   {
731   const pcre *regex_islookupmod = regex_must_compile(
732     US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
733 
734   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
735   while ((ent = readdir(dd)))
736     {
737     char *name = ent->d_name;
738     int len = (int)strlen(name);
739     if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0)
740       {
741       int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
742       void *dl;
743       struct lookup_module_info *info;
744       const char *errormsg;
745 
746       /* SRH: am I being paranoid here or what? */
747       if (pathnamelen > big_buffer_size)
748 	{
749 	fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
750 	log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
751 	continue;
752 	}
753 
754       /* SRH: snprintf here? */
755       sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
756 
757       if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
758 	{
759 	errormsg = dlerror();
760 	fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
761 	log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
762 	moduleerrors++;
763 	continue;
764 	}
765 
766       /* FreeBSD nsdispatch() can trigger dlerror() errors about
767       _nss_cache_cycle_prevention_function; we need to clear the dlerror()
768       state before calling dlsym(), so that any error afterwards only comes
769       from dlsym().  */
770 
771       errormsg = dlerror();
772 
773       info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
774       if ((errormsg = dlerror()))
775 	{
776 	fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
777 	log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
778 	dlclose(dl);
779 	moduleerrors++;
780 	continue;
781 	}
782       if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
783 	{
784 	fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
785 	log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
786 	dlclose(dl);
787 	moduleerrors++;
788 	continue;
789 	}
790 
791       addlookupmodule(dl, info);
792       DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
793       countmodules++;
794       }
795     }
796   store_free((void*)regex_islookupmod);
797   closedir(dd);
798   }
799 
800 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
801 #endif
802 
803 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
804 
805 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
806 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
807 
808 /* now add all lookups to the real list */
809 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
810   for (int j = 0; j < p->info->lookupcount; j++)
811     add_lookup_to_list(p->info->lookups[j]);
812 store_reset(reset_point);
813 /* just to be sure */
814 lookupmodules = NULL;
815 }
816 
817 #endif	/*!MACRO_PREDEF*/
818 /* End of drtables.c */
819