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