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