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