Add dynamic lookup support
[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 */