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