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