Implemented gsasl driver for authentication.
[exim.git] / src / src / drtables.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8
9 #include "exim.h"
10
11 #include <string.h>
12
13 /* This module contains tables that define the lookup methods and drivers
14 that are actually included in the binary. Its contents are controlled by
15 various macros in config.h that ultimately come from Local/Makefile. They are
16 all described in src/EDITME. */
17
18
19 lookup_info **lookup_list;
20 int lookup_list_count = 0;
21
22 static int lookup_list_init_done = 0;
23
24 /* Table of information about all possible authentication mechamisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set 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
36 #ifdef AUTH_DOVECOT
37 #include "auths/dovecot.h"
38 #endif
39
40 #ifdef AUTH_GSASL
41 #include "auths/gsasl_exim.h"
42 #endif
43
44 #ifdef AUTH_PLAINTEXT
45 #include "auths/plaintext.h"
46 #endif
47
48 #ifdef AUTH_SPA
49 #include "auths/spa.h"
50 #endif
51
52 auth_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 */
65   auth_cram_md5_client,                      /* client function */
66   NULL                                       /* diagnostic function */
67   },
68 #endif
69
70 #ifdef AUTH_CYRUS_SASL
71   {
72   US"cyrus_sasl",           /* lookup name */
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 */
79   NULL,                                      /* client function */
80   auth_cyrus_sasl_version_report             /* diagnostic function */
81   },
82 #endif
83
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 */
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 */
109   },
110 #endif
111
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 */
121   auth_plaintext_client,                     /* client function */
122   NULL                                       /* diagnostic function */
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 */
135   auth_spa_client,                           /* client function */
136   NULL                                       /* diagnostic function */
137   },
138 #endif
139
140 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL  }
141 };
142
143
144 /* Tables of information about which routers and transports are included in the
145 exim 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
202 router_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
299 transport_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
373 struct lookupmodulestr
374 {
375   void *dl;
376   struct lookup_module_info *info;
377   struct lookupmodulestr *next;
378 };
379
380 static struct lookupmodulestr *lookupmodules = NULL;
381
382 static 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 */
393 static 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
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
421 extern lookup_module_info whoson_lookup_module_info;
422 #endif
423 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
424 extern lookup_module_info testdb_lookup_module_info;
425 #endif
426 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
427 extern lookup_module_info sqlite_lookup_module_info;
428 #endif
429 #ifdef EXPERIMENTAL_SPF
430 extern lookup_module_info spf_lookup_module_info;
431 #endif
432 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
433 extern lookup_module_info pgsql_lookup_module_info;
434 #endif
435 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
436 extern lookup_module_info passwd_lookup_module_info;
437 #endif
438 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
439 extern lookup_module_info oracle_lookup_module_info;
440 #endif
441 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
442 extern lookup_module_info nisplus_lookup_module_info;
443 #endif
444 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
445 extern lookup_module_info nis_lookup_module_info;
446 #endif
447 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
448 extern lookup_module_info mysql_lookup_module_info;
449 #endif
450 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
451 extern lookup_module_info lsearch_lookup_module_info;
452 #endif
453 #ifdef LOOKUP_LDAP
454 extern lookup_module_info ldap_lookup_module_info;
455 #endif
456 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
457 extern lookup_module_info ibase_lookup_module_info;
458 #endif
459 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
460 extern lookup_module_info dsearch_lookup_module_info;
461 #endif
462 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
463 extern lookup_module_info dnsdb_lookup_module_info;
464 #endif
465 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
466 extern lookup_module_info dbmdb_lookup_module_info;
467 #endif
468 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
469 extern lookup_module_info cdb_lookup_module_info;
470 #endif
471
472 void init_lookup_list(void)
473 {
474   DIR *dd;
475   struct dirent *ent;
476   const pcre *regex_islookupmod = regex_must_compile(
477       US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
478   int countmodules = 0;
479   int moduleerrors = 0;
480   struct lookupmodulestr *p;
481
482   if (lookup_list_init_done)
483     return;
484   lookup_list_init_done = 1;
485
486 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
487   addlookupmodule(NULL, &cdb_lookup_module_info);
488 #endif
489
490 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
491   addlookupmodule(NULL, &dbmdb_lookup_module_info);
492 #endif
493
494 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
495   addlookupmodule(NULL, &dnsdb_lookup_module_info);
496 #endif
497
498 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
499   addlookupmodule(NULL, &dsearch_lookup_module_info);
500 #endif
501
502 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
503   addlookupmodule(NULL, &ibase_lookup_module_info);
504 #endif
505
506 #ifdef LOOKUP_LDAP
507   addlookupmodule(NULL, &ldap_lookup_module_info);
508 #endif
509
510 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
511   addlookupmodule(NULL, &lsearch_lookup_module_info);
512 #endif
513
514 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
515   addlookupmodule(NULL, &mysql_lookup_module_info);
516 #endif
517
518 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
519   addlookupmodule(NULL, &nis_lookup_module_info);
520 #endif
521
522 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
523   addlookupmodule(NULL, &nisplus_lookup_module_info);
524 #endif
525
526 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
527   addlookupmodule(NULL, &oracle_lookup_module_info);
528 #endif
529
530 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
531   addlookupmodule(NULL, &passwd_lookup_module_info);
532 #endif
533
534 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
535   addlookupmodule(NULL, &pgsql_lookup_module_info);
536 #endif
537
538 #ifdef EXPERIMENTAL_SPF
539   addlookupmodule(NULL, &spf_lookup_module_info);
540 #endif
541
542 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
543   addlookupmodule(NULL, &sqlite_lookup_module_info);
544 #endif
545
546 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
547   addlookupmodule(NULL, &testdb_lookup_module_info);
548 #endif
549
550 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
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) {
557     DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
558     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
559   }
560   else {
561     DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
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;
569         const char *errormsg;
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
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
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);
613         DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
614         countmodules++;
615       }
616     }
617     closedir(dd);
618   }
619
620   DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
621 #endif
622
623   store_free((void*)regex_islookupmod);
624
625   DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
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
647 /* End of drtables.c */