Merge branch 'list_safety'
[exim.git] / src / src / drtables.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
0a49a7a4 5/* Copyright (c) University of Cambridge 1995 - 2009 */
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
6545de78
PP
22static int lookup_list_init_done = 0;
23
059ec3d9
PH
24/* Table of information about all possible authentication mechamisms. All
25entries are always present if any mechanism is declared, but the functions are
26set to NULL for those that are not compiled into the binary. */
27
28#ifdef AUTH_CRAM_MD5
29#include "auths/cram_md5.h"
30#endif
31
32#ifdef AUTH_CYRUS_SASL
33#include "auths/cyrus_sasl.h"
34#endif
35
14aa5a05
PH
36#ifdef AUTH_DOVECOT
37#include "auths/dovecot.h"
38#endif
39
059ec3d9
PH
40#ifdef AUTH_PLAINTEXT
41#include "auths/plaintext.h"
42#endif
43
44#ifdef AUTH_SPA
45#include "auths/spa.h"
46#endif
47
48auth_info auths_available[] = {
49
50/* Checking by an expansion condition on plain text */
51
52#ifdef AUTH_CRAM_MD5
53 {
54 US"cram_md5", /* lookup name */
55 auth_cram_md5_options,
56 &auth_cram_md5_options_count,
57 &auth_cram_md5_option_defaults,
58 sizeof(auth_cram_md5_options_block),
59 auth_cram_md5_init, /* init function */
60 auth_cram_md5_server, /* server function */
61 auth_cram_md5_client /* client function */
62 },
63#endif
64
65#ifdef AUTH_CYRUS_SASL
66 {
384152a6 67 US"cyrus_sasl", /* lookup name */
059ec3d9
PH
68 auth_cyrus_sasl_options,
69 &auth_cyrus_sasl_options_count,
70 &auth_cyrus_sasl_option_defaults,
71 sizeof(auth_cyrus_sasl_options_block),
72 auth_cyrus_sasl_init, /* init function */
73 auth_cyrus_sasl_server, /* server function */
74 NULL /* client function */
75 },
76#endif
77
14aa5a05
PH
78#ifdef AUTH_DOVECOT
79 {
80 US"dovecot", /* lookup name */
81 auth_dovecot_options,
82 &auth_dovecot_options_count,
83 &auth_dovecot_option_defaults,
84 sizeof(auth_dovecot_options_block),
85 auth_dovecot_init, /* init function */
86 auth_dovecot_server, /* server function */
87 NULL /* client function */
88 },
89#endif
90
059ec3d9
PH
91#ifdef AUTH_PLAINTEXT
92 {
93 US"plaintext", /* lookup name */
94 auth_plaintext_options,
95 &auth_plaintext_options_count,
96 &auth_plaintext_option_defaults,
97 sizeof(auth_plaintext_options_block),
98 auth_plaintext_init, /* init function */
99 auth_plaintext_server, /* server function */
100 auth_plaintext_client /* client function */
101 },
102#endif
103
104#ifdef AUTH_SPA
105 {
106 US"spa", /* lookup name */
107 auth_spa_options,
108 &auth_spa_options_count,
109 &auth_spa_option_defaults,
110 sizeof(auth_spa_options_block),
111 auth_spa_init, /* init function */
112 auth_spa_server, /* server function */
113 auth_spa_client /* client function */
114 },
115#endif
116
117{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL }
118};
119
120
121/* Tables of information about which routers and transports are included in the
122exim binary. */
123
124/* Pull in the necessary header files */
125
126#include "routers/rf_functions.h"
127
128#ifdef ROUTER_ACCEPT
129#include "routers/accept.h"
130#endif
131
132#ifdef ROUTER_DNSLOOKUP
133#include "routers/dnslookup.h"
134#endif
135
136#ifdef ROUTER_MANUALROUTE
137#include "routers/manualroute.h"
138#endif
139
140#ifdef ROUTER_IPLITERAL
141#include "routers/ipliteral.h"
142#endif
143
144#ifdef ROUTER_IPLOOKUP
145#include "routers/iplookup.h"
146#endif
147
148#ifdef ROUTER_QUERYPROGRAM
149#include "routers/queryprogram.h"
150#endif
151
152#ifdef ROUTER_REDIRECT
153#include "routers/redirect.h"
154#endif
155
156#ifdef TRANSPORT_APPENDFILE
157#include "transports/appendfile.h"
158#endif
159
160#ifdef TRANSPORT_AUTOREPLY
161#include "transports/autoreply.h"
162#endif
163
164#ifdef TRANSPORT_LMTP
165#include "transports/lmtp.h"
166#endif
167
168#ifdef TRANSPORT_PIPE
169#include "transports/pipe.h"
170#endif
171
172#ifdef TRANSPORT_SMTP
173#include "transports/smtp.h"
174#endif
175
176
177/* Now set up the structures, terminated by an entry with a null name. */
178
179router_info routers_available[] = {
180#ifdef ROUTER_ACCEPT
181 {
182 US"accept",
183 accept_router_options,
184 &accept_router_options_count,
185 &accept_router_option_defaults,
186 sizeof(accept_router_options_block),
187 accept_router_init,
188 accept_router_entry,
189 NULL, /* no tidyup entry */
190 ri_yestransport
191 },
192#endif
193#ifdef ROUTER_DNSLOOKUP
194 {
195 US"dnslookup",
196 dnslookup_router_options,
197 &dnslookup_router_options_count,
198 &dnslookup_router_option_defaults,
199 sizeof(dnslookup_router_options_block),
200 dnslookup_router_init,
201 dnslookup_router_entry,
202 NULL, /* no tidyup entry */
203 ri_yestransport
204 },
205#endif
206#ifdef ROUTER_IPLITERAL
207 {
208 US"ipliteral",
209 ipliteral_router_options,
210 &ipliteral_router_options_count,
211 &ipliteral_router_option_defaults,
212 sizeof(ipliteral_router_options_block),
213 ipliteral_router_init,
214 ipliteral_router_entry,
215 NULL, /* no tidyup entry */
216 ri_yestransport
217 },
218#endif
219#ifdef ROUTER_IPLOOKUP
220 {
221 US"iplookup",
222 iplookup_router_options,
223 &iplookup_router_options_count,
224 &iplookup_router_option_defaults,
225 sizeof(iplookup_router_options_block),
226 iplookup_router_init,
227 iplookup_router_entry,
228 NULL, /* no tidyup entry */
229 ri_notransport
230 },
231#endif
232#ifdef ROUTER_MANUALROUTE
233 {
234 US"manualroute",
235 manualroute_router_options,
236 &manualroute_router_options_count,
237 &manualroute_router_option_defaults,
238 sizeof(manualroute_router_options_block),
239 manualroute_router_init,
240 manualroute_router_entry,
241 NULL, /* no tidyup entry */
242 0
243 },
244#endif
245#ifdef ROUTER_QUERYPROGRAM
246 {
247 US"queryprogram",
248 queryprogram_router_options,
249 &queryprogram_router_options_count,
250 &queryprogram_router_option_defaults,
251 sizeof(queryprogram_router_options_block),
252 queryprogram_router_init,
253 queryprogram_router_entry,
254 NULL, /* no tidyup entry */
255 0
256 },
257#endif
258#ifdef ROUTER_REDIRECT
259 {
260 US"redirect",
261 redirect_router_options,
262 &redirect_router_options_count,
263 &redirect_router_option_defaults,
264 sizeof(redirect_router_options_block),
265 redirect_router_init,
266 redirect_router_entry,
267 NULL, /* no tidyup entry */
268 ri_notransport
269 },
270#endif
271{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
272};
273
274
275
276transport_info transports_available[] = {
277#ifdef TRANSPORT_APPENDFILE
278 {
279 US"appendfile", /* driver name */
280 appendfile_transport_options, /* local options table */
281 &appendfile_transport_options_count, /* number of entries */
282 &appendfile_transport_option_defaults, /* private options defaults */
283 sizeof(appendfile_transport_options_block), /* size of private block */
284 appendfile_transport_init, /* init entry point */
285 appendfile_transport_entry, /* main entry point */
286 NULL, /* no tidyup entry */
287 NULL, /* no closedown entry */
288 TRUE, /* local flag */
289 },
290#endif
291#ifdef TRANSPORT_AUTOREPLY
292 {
293 US"autoreply", /* driver name */
294 autoreply_transport_options, /* local options table */
295 &autoreply_transport_options_count, /* number of entries */
296 &autoreply_transport_option_defaults, /* private options defaults */
297 sizeof(autoreply_transport_options_block), /* size of private block */
298 autoreply_transport_init, /* init entry point */
299 autoreply_transport_entry, /* main entry point */
300 NULL, /* no tidyup entry */
301 NULL, /* no closedown entry */
302 TRUE /* local flag */
303 },
304#endif
305#ifdef TRANSPORT_LMTP
306 {
307 US"lmtp", /* driver name */
308 lmtp_transport_options, /* local options table */
309 &lmtp_transport_options_count, /* number of entries */
310 &lmtp_transport_option_defaults, /* private options defaults */
311 sizeof(lmtp_transport_options_block), /* size of private block */
312 lmtp_transport_init, /* init entry point */
313 lmtp_transport_entry, /* main entry point */
314 NULL, /* no tidyup entry */
315 NULL, /* no closedown entry */
316 TRUE /* local flag */
317 },
318#endif
319#ifdef TRANSPORT_PIPE
320 {
321 US"pipe", /* driver name */
322 pipe_transport_options, /* local options table */
323 &pipe_transport_options_count, /* number of entries */
324 &pipe_transport_option_defaults, /* private options defaults */
325 sizeof(pipe_transport_options_block), /* size of private block */
326 pipe_transport_init, /* init entry point */
327 pipe_transport_entry, /* main entry point */
328 NULL, /* no tidyup entry */
329 NULL, /* no closedown entry */
330 TRUE /* local flag */
331 },
332#endif
333#ifdef TRANSPORT_SMTP
334 {
335 US"smtp", /* driver name */
336 smtp_transport_options, /* local options table */
337 &smtp_transport_options_count, /* number of entries */
338 &smtp_transport_option_defaults, /* private options defaults */
339 sizeof(smtp_transport_options_block), /* size of private block */
340 smtp_transport_init, /* init entry point */
341 smtp_transport_entry, /* main entry point */
342 NULL, /* no tidyup entry */
343 smtp_transport_closedown, /* close down passed channel */
344 FALSE /* local flag */
345 },
346#endif
347{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, FALSE }
348};
349
e6d225ae
DW
350struct lookupmodulestr
351{
352 void *dl;
353 struct lookup_module_info *info;
354 struct lookupmodulestr *next;
355};
356
357static struct lookupmodulestr *lookupmodules = NULL;
358
359static void addlookupmodule(void *dl, struct lookup_module_info *info)
360{
361 struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
362 p->dl = dl;
363 p->info = info;
364 p->next = lookupmodules;
365 lookupmodules = p;
366 lookup_list_count += info->lookupcount;
367}
368
369/* only valid after lookup_list and lookup_list_count are assigned */
370static void add_lookup_to_list(lookup_info *info)
371{
372 /* need to add the lookup to lookup_list, sorted */
373 int pos = 0;
374
375 /* strategy is to go through the list until we find
376 * either an empty spot or a name that is higher.
377 * this can't fail because we have enough space. */
378 while (lookup_list[pos]
379 && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0)) {
380 pos++;
381 }
382 if (lookup_list[pos]) {
383 /* need to insert it, so move all the other items up
384 * (last slot is still empty, of course) */
385 memmove(&lookup_list[pos+1],
386 &lookup_list[pos],
387 sizeof(lookup_info **) * (lookup_list_count-pos-1));
388 }
389 lookup_list[pos] = info;
390}
391
4d805ee9
PP
392
393/* These need to be at file level for old versions of gcc (2.95.2 reported),
394 * which give parse errors on an extern in function scope. Each entry needs
395 * to also be invoked in init_lookup_list() below */
396
397#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
398extern lookup_module_info whoson_lookup_module_info;
399#endif
400#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
401extern lookup_module_info testdb_lookup_module_info;
402#endif
403#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
404extern lookup_module_info sqlite_lookup_module_info;
405#endif
406#ifdef EXPERIMENTAL_SPF
407extern lookup_module_info spf_lookup_module_info;
408#endif
409#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
410extern lookup_module_info pgsql_lookup_module_info;
411#endif
412#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
413extern lookup_module_info passwd_lookup_module_info;
414#endif
415#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
416extern lookup_module_info oracle_lookup_module_info;
417#endif
418#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
419extern lookup_module_info nisplus_lookup_module_info;
420#endif
421#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
422extern lookup_module_info nis_lookup_module_info;
423#endif
424#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
425extern lookup_module_info mysql_lookup_module_info;
426#endif
427#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
428extern lookup_module_info lsearch_lookup_module_info;
429#endif
430#ifdef LOOKUP_LDAP
431extern lookup_module_info ldap_lookup_module_info;
432#endif
433#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
434extern lookup_module_info ibase_lookup_module_info;
435#endif
436#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
437extern lookup_module_info dsearch_lookup_module_info;
438#endif
439#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
440extern lookup_module_info dnsdb_lookup_module_info;
441#endif
442#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
443extern lookup_module_info dbmdb_lookup_module_info;
444#endif
445#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
446extern lookup_module_info cdb_lookup_module_info;
447#endif
448
e6d225ae
DW
449void init_lookup_list(void)
450{
451 DIR *dd;
452 struct dirent *ent;
e12f8c32
PP
453 const pcre *regex_islookupmod = regex_must_compile(
454 US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
e6d225ae
DW
455 int countmodules = 0;
456 int moduleerrors = 0;
457 struct lookupmodulestr *p;
458
6545de78
PP
459 if (lookup_list_init_done)
460 return;
461 lookup_list_init_done = 1;
462
e6d225ae 463#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
e6d225ae
DW
464 addlookupmodule(NULL, &cdb_lookup_module_info);
465#endif
466
467#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
e6d225ae
DW
468 addlookupmodule(NULL, &dbmdb_lookup_module_info);
469#endif
470
471#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
e6d225ae
DW
472 addlookupmodule(NULL, &dnsdb_lookup_module_info);
473#endif
474
475#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
e6d225ae
DW
476 addlookupmodule(NULL, &dsearch_lookup_module_info);
477#endif
478
479#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
e6d225ae
DW
480 addlookupmodule(NULL, &ibase_lookup_module_info);
481#endif
482
483#ifdef LOOKUP_LDAP
e6d225ae
DW
484 addlookupmodule(NULL, &ldap_lookup_module_info);
485#endif
486
487#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
e6d225ae
DW
488 addlookupmodule(NULL, &lsearch_lookup_module_info);
489#endif
490
491#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
e6d225ae
DW
492 addlookupmodule(NULL, &mysql_lookup_module_info);
493#endif
494
495#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
e6d225ae
DW
496 addlookupmodule(NULL, &nis_lookup_module_info);
497#endif
498
499#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
e6d225ae
DW
500 addlookupmodule(NULL, &nisplus_lookup_module_info);
501#endif
502
503#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
e6d225ae
DW
504 addlookupmodule(NULL, &oracle_lookup_module_info);
505#endif
506
507#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
e6d225ae
DW
508 addlookupmodule(NULL, &passwd_lookup_module_info);
509#endif
510
511#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
e6d225ae
DW
512 addlookupmodule(NULL, &pgsql_lookup_module_info);
513#endif
514
515#ifdef EXPERIMENTAL_SPF
e6d225ae
DW
516 addlookupmodule(NULL, &spf_lookup_module_info);
517#endif
518
519#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
e6d225ae
DW
520 addlookupmodule(NULL, &sqlite_lookup_module_info);
521#endif
522
523#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
e6d225ae
DW
524 addlookupmodule(NULL, &testdb_lookup_module_info);
525#endif
526
527#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
e6d225ae
DW
528 addlookupmodule(NULL, &whoson_lookup_module_info);
529#endif
530
531#ifdef LOOKUP_MODULE_DIR
532 dd = opendir(LOOKUP_MODULE_DIR);
533 if (dd == NULL) {
1594a79a 534 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
e6d225ae
DW
535 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
536 }
537 else {
1594a79a 538 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
e6d225ae
DW
539 while ((ent = readdir(dd)) != NULL) {
540 char *name = ent->d_name;
541 int len = (int)strlen(name);
542 if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
543 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
544 void *dl;
545 struct lookup_module_info *info;
1ba28e2b 546 const char *errormsg;
e6d225ae
DW
547
548 /* SRH: am I being paranoid here or what? */
549 if (pathnamelen > big_buffer_size) {
550 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
551 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
552 continue;
553 }
554
555 /* SRH: snprintf here? */
556 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
557
558 dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
559 if (dl == NULL) {
560 fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
561 moduleerrors++;
562 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
563 continue;
564 }
565
56e0c4ce
PP
566 /* FreeBSD nsdispatch() can trigger dlerror() errors about
567 * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
568 * state before calling dlsym(), so that any error afterwards only
569 * comes from dlsym().
570 */
571 errormsg = dlerror();
572
e6d225ae
DW
573 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
574 if ((errormsg = dlerror()) != NULL) {
575 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
576 dlclose(dl);
577 moduleerrors++;
578 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
579 continue;
580 }
581 if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
582 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
583 dlclose(dl);
584 moduleerrors++;
585 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
586 continue;
587 }
588
589 addlookupmodule(dl, info);
1594a79a 590 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
e6d225ae
DW
591 countmodules++;
592 }
593 }
594 closedir(dd);
595 }
596
1594a79a 597 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
e6d225ae
DW
598#endif
599
600 store_free((void*)regex_islookupmod);
601
1594a79a 602 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
e6d225ae
DW
603
604 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
605 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
606
607 /* now add all lookups to the real list */
608 p = lookupmodules;
609 while (p) {
610 int j;
611 struct lookupmodulestr *pnext;
612
613 for (j = 0; j < p->info->lookupcount; j++)
614 add_lookup_to_list(p->info->lookups[j]);
615
616 pnext = p->next;
617 store_free(p);
618 p = pnext;
619 }
620 /* just to be sure */
621 lookupmodules = NULL;
622}
623
059ec3d9 624/* End of drtables.c */