1d8e222e2d2e8efe9d6f6fda555cf408a56fe3c4
[exim.git] / src / src / drtables.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10
11 #include "exim.h"
12
13 #include <string.h>
14
15 /* This module contains tables that define the lookup methods and drivers
16 that are actually included in the binary. Its contents are controlled by
17 various macros in config.h that ultimately come from Local/Makefile. They are
18 all described in src/EDITME. */
19
20
21 lookup_info **lookup_list;
22 int lookup_list_count = 0;
23
24 /* Lists of information about which drivers are included in the exim binary. */
25
26 auth_info * auths_available= NULL;
27 router_info * routers_available = NULL;
28 transport_info * transports_available = NULL;
29
30
31
32 #ifndef MACRO_PREDEF
33
34 gstring *
35 auth_show_supported(gstring * g)
36 {
37 uschar * b = US""               /* static-build authenticatornames */
38 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
39   " cram_md5"
40 #endif
41 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
42   " cyrus_sasl"
43 #endif
44 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
45   " dovecot"
46 #endif
47 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
48   " external"
49 #endif
50 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
51   " gsasl"
52 #endif
53 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
54   " heimdal_gssapi"
55 #endif
56 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
57   " plaintext"
58 #endif
59 #if defined(AUTH_SPA) && AUTH_SPA!=2
60   " spa"
61 #endif
62 #if defined(AUTH_TLS) && AUTH_TLS!=2
63   " tls"
64 #endif
65   ;
66
67 uschar * d = US""               /* dynamic-module authenticator names */
68 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
69   " cram_md5"
70 #endif
71 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
72   " cyrus_sasl"
73 #endif
74 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
75   " dovecot"
76 #endif
77 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
78   " external"
79 #endif
80 #if defined(AUTH_GSASL) && AUTH_GSASL==2
81   " gsasl"
82 #endif
83 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
84   " heimdal_gssapi"
85 #endif
86 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
87   " plaintext"
88 #endif
89 #if defined(AUTH_SPA) && AUTH_SPA==2
90   " spa"
91 #endif
92 #if defined(AUTH_TLS) && AUTH_TLS==2
93   " tls"
94 #endif
95   ;
96
97 if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
98 if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
99 return g;
100 }
101
102 gstring *
103 route_show_supported(gstring * g)
104 {
105 uschar * b = US""               /* static-build router names */
106 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
107   " accept"
108 #endif
109 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
110   " dnslookup"
111 #endif
112 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
113   " ipliteral"
114 #endif
115 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
116   " iplookup"
117 #endif
118 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
119   " manualroute"
120 #endif
121 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
122   " redirect"
123 #endif
124 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
125   " queryprogram"
126 #endif
127   ;
128
129 uschar * d = US""               /* dynamic-module router names */
130 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
131   " accept"
132 #endif
133 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
134   " dnslookup"
135 #endif
136 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
137   " ipliteral"
138 #endif
139 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
140   " iplookup"
141 #endif
142 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
143   " manualroute"
144 #endif
145 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
146   " redirect"
147 #endif
148 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
149   " queryprogram"
150 #endif
151   ;
152
153 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
154 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
155 return g;
156 }
157
158 gstring *
159 transport_show_supported(gstring * g)
160 {
161 uschar * b = US""               /* static-build transportnames */
162 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
163   " appendfile"
164 # ifdef SUPPORT_MAILDIR
165     "/maildir"
166 # endif
167 # ifdef SUPPORT_MAILSTORE
168     "/mailstore"
169 # endif
170 # ifdef SUPPORT_MBX
171     "/mbx"
172 # endif
173 #endif
174 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
175   " autoreply"
176 #endif
177 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
178   " lmtp"
179 #endif
180 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
181   " pipe"
182 #endif
183 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
184   " queuefile"
185 #endif
186 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
187   " smtp"
188 #endif
189   ;
190
191 uschar * d = US""               /* dynamic-module transportnames */
192 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
193   " appendfile"
194 # ifdef SUPPORT_MAILDIR
195     "/maildir"
196 # endif
197 # ifdef SUPPORT_MAILSTORE
198     "/mailstore"
199 # endif
200 # ifdef SUPPORT_MBX
201     "/mbx"
202 # endif
203 #endif
204 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
205   " autoreply"
206 #endif
207 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
208   " lmtp"
209 #endif
210 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
211   " pipe"
212 #endif
213 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
214   " queuefile"
215 #endif
216 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
217   " smtp"
218 #endif
219   ;
220
221 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
222 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
223 return g;
224 }
225
226
227
228 struct lookupmodulestr
229 {
230   void *dl;
231   struct lookup_module_info *info;
232   struct lookupmodulestr *next;
233 };
234
235 static struct lookupmodulestr *lookupmodules = NULL;
236
237 static void
238 addlookupmodule(void *dl, struct lookup_module_info *info)
239 {
240 struct lookupmodulestr * p =
241   store_get(sizeof(struct lookupmodulestr), GET_UNTAINTED);
242
243 p->dl = dl;
244 p->info = info;
245 p->next = lookupmodules;
246 lookupmodules = p;
247 lookup_list_count += info->lookupcount;
248 }
249
250 /* only valid after lookup_list and lookup_list_count are assigned */
251 static void
252 add_lookup_to_list(lookup_info *info)
253 {
254 /* need to add the lookup to lookup_list, sorted */
255 int pos = 0;
256
257 /* strategy is to go through the list until we find
258 either an empty spot or a name that is higher.
259 this can't fail because we have enough space. */
260
261 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
262   pos++;
263
264 if (lookup_list[pos])
265   {
266   /* need to insert it, so move all the other items up
267   (last slot is still empty, of course) */
268
269   memmove(&lookup_list[pos+1], &lookup_list[pos],
270           sizeof(lookup_info *) * (lookup_list_count-pos-1));
271   }
272 lookup_list[pos] = info;
273 }
274
275
276 /* These need to be at file level for old versions of gcc (2.95.2 reported),
277 which give parse errors on an extern in function scope.  Each entry needs
278 to also be invoked in init_lookup_list() below  */
279
280 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
281 extern lookup_module_info cdb_lookup_module_info;
282 #endif
283 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
284 extern lookup_module_info dbmdb_lookup_module_info;
285 #endif
286 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
287 extern lookup_module_info dnsdb_lookup_module_info;
288 #endif
289 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
290 extern lookup_module_info dsearch_lookup_module_info;
291 #endif
292 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
293 extern lookup_module_info ibase_lookup_module_info;
294 #endif
295 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
296 extern lookup_module_info json_lookup_module_info;
297 #endif
298 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
299 extern lookup_module_info ldap_lookup_module_info;
300 #endif
301 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
302 extern lookup_module_info lsearch_lookup_module_info;
303 #endif
304 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
305 extern lookup_module_info mysql_lookup_module_info;
306 #endif
307 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
308 extern lookup_module_info nis_lookup_module_info;
309 #endif
310 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
311 extern lookup_module_info nisplus_lookup_module_info;
312 #endif
313 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
314 extern lookup_module_info oracle_lookup_module_info;
315 #endif
316 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
317 extern lookup_module_info passwd_lookup_module_info;
318 #endif
319 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
320 extern lookup_module_info pgsql_lookup_module_info;
321 #endif
322 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
323 extern lookup_module_info redis_lookup_module_info;
324 #endif
325 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
326 extern lookup_module_info lmdb_lookup_module_info;
327 #endif
328 #if defined(SUPPORT_SPF)
329 extern lookup_module_info spf_lookup_module_info;
330 #endif
331 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
332 extern lookup_module_info sqlite_lookup_module_info;
333 #endif
334 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
335 extern lookup_module_info testdb_lookup_module_info;
336 #endif
337 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
338 extern lookup_module_info whoson_lookup_module_info;
339 #endif
340
341 extern lookup_module_info readsock_lookup_module_info;
342
343
344 void
345 init_lookup_list(void)
346 {
347 #ifdef LOOKUP_MODULE_DIR
348 DIR * dd;
349 struct dirent * ent;
350 int countmodules = 0;
351 int moduleerrors = 0;
352 #endif
353 static BOOL lookup_list_init_done = FALSE;
354 rmark reset_point;
355
356 if (lookup_list_init_done)
357   return;
358 reset_point = store_mark();
359 lookup_list_init_done = TRUE;
360
361 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
362 addlookupmodule(NULL, &cdb_lookup_module_info);
363 #endif
364
365 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
366 addlookupmodule(NULL, &dbmdb_lookup_module_info);
367 #endif
368
369 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
370 addlookupmodule(NULL, &dnsdb_lookup_module_info);
371 #endif
372
373 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
374 addlookupmodule(NULL, &dsearch_lookup_module_info);
375 #endif
376
377 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
378 addlookupmodule(NULL, &ibase_lookup_module_info);
379 #endif
380
381 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
382 addlookupmodule(NULL, &ldap_lookup_module_info);
383 #endif
384
385 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
386 addlookupmodule(NULL, &json_lookup_module_info);
387 #endif
388
389 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
390 addlookupmodule(NULL, &lsearch_lookup_module_info);
391 #endif
392
393 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
394 addlookupmodule(NULL, &mysql_lookup_module_info);
395 #endif
396
397 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
398 addlookupmodule(NULL, &nis_lookup_module_info);
399 #endif
400
401 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
402 addlookupmodule(NULL, &nisplus_lookup_module_info);
403 #endif
404
405 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
406 addlookupmodule(NULL, &oracle_lookup_module_info);
407 #endif
408
409 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
410 addlookupmodule(NULL, &passwd_lookup_module_info);
411 #endif
412
413 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
414 addlookupmodule(NULL, &pgsql_lookup_module_info);
415 #endif
416
417 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
418 addlookupmodule(NULL, &redis_lookup_module_info);
419 #endif
420
421 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
422 addlookupmodule(NULL, &lmdb_lookup_module_info);
423 #endif
424
425 #ifdef SUPPORT_SPF
426 addlookupmodule(NULL, &spf_lookup_module_info);
427 #endif
428
429 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
430 addlookupmodule(NULL, &sqlite_lookup_module_info);
431 #endif
432
433 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
434 addlookupmodule(NULL, &testdb_lookup_module_info);
435 #endif
436
437 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
438 addlookupmodule(NULL, &whoson_lookup_module_info);
439 #endif
440
441 /* This is a custom expansion, and not available as either
442 a list-syntax lookup or a lookup expansion. However, it is
443 implemented by a lookup module. */
444
445 addlookupmodule(NULL, &readsock_lookup_module_info);
446
447 #ifdef LOOKUP_MODULE_DIR
448 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
449   {
450   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
451   log_write(0, LOG_MAIN|LOG_PANIC,
452           "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
453   }
454 else
455   {
456   const pcre2_code * regex_islookupmod = regex_must_compile(
457     US"_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
458
459   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
460   while ((ent = readdir(dd)))
461     {
462     char * name = ent->d_name;
463     int len = (int)strlen(name);
464     if (regex_match(regex_islookupmod, US name, len, NULL))
465       {
466       int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
467       void *dl;
468       struct lookup_module_info *info;
469       const char *errormsg;
470
471       /* SRH: am I being paranoid here or what? */
472       if (pathnamelen > big_buffer_size)
473         {
474         fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
475         log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
476         continue;
477         }
478
479       /* SRH: snprintf here? */
480       sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
481
482       if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
483         {
484         errormsg = dlerror();
485         fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
486         log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
487         moduleerrors++;
488         continue;
489         }
490
491       /* FreeBSD nsdispatch() can trigger dlerror() errors about
492       _nss_cache_cycle_prevention_function; we need to clear the dlerror()
493       state before calling dlsym(), so that any error afterwards only comes
494       from dlsym().  */
495
496       errormsg = dlerror();
497
498       info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
499       if ((errormsg = dlerror()))
500         {
501         fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
502         log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
503         dlclose(dl);
504         moduleerrors++;
505         continue;
506         }
507       if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
508         {
509         fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
510         log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
511         dlclose(dl);
512         moduleerrors++;
513         continue;
514         }
515
516       addlookupmodule(dl, info);
517       DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
518       countmodules++;
519       }
520     }
521   store_free((void*)regex_islookupmod);
522   closedir(dd);
523   }
524
525 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
526 #endif
527
528 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
529
530 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
531 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
532
533 /* now add all lookups to the real list */
534 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
535   for (int j = 0; j < p->info->lookupcount; j++)
536     add_lookup_to_list(p->info->lookups[j]);
537 store_reset(reset_point);
538 /* just to be sure */
539 lookupmodules = NULL;
540 }
541
542 #endif  /*!MACRO_PREDEF*/
543 /* End of drtables.c */