a144085c5a797397c356ecce68ad46b45fab503b
[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 tree_node * lookups_tree = NULL;
23 unsigned lookup_list_count = 0;
24
25 /* Lists of information about which drivers are included in the exim binary. */
26
27 auth_info * auths_available= NULL;
28 router_info * routers_available = NULL;
29 transport_info * transports_available = NULL;
30
31
32
33 #ifndef MACRO_PREDEF
34
35 gstring *
36 auth_show_supported(gstring * g)
37 {
38 uschar * b = US""               /* static-build authenticatornames */
39 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
40   " cram_md5"
41 #endif
42 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
43   " cyrus_sasl"
44 #endif
45 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
46   " dovecot"
47 #endif
48 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
49   " external"
50 #endif
51 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
52   " gsasl"
53 #endif
54 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
55   " heimdal_gssapi"
56 #endif
57 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
58   " plaintext"
59 #endif
60 #if defined(AUTH_SPA) && AUTH_SPA!=2
61   " spa"
62 #endif
63 #if defined(AUTH_TLS) && AUTH_TLS!=2
64   " tls"
65 #endif
66   ;
67
68 uschar * d = US""               /* dynamic-module authenticator names */
69 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
70   " cram_md5"
71 #endif
72 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
73   " cyrus_sasl"
74 #endif
75 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
76   " dovecot"
77 #endif
78 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
79   " external"
80 #endif
81 #if defined(AUTH_GSASL) && AUTH_GSASL==2
82   " gsasl"
83 #endif
84 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
85   " heimdal_gssapi"
86 #endif
87 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
88   " plaintext"
89 #endif
90 #if defined(AUTH_SPA) && AUTH_SPA==2
91   " spa"
92 #endif
93 #if defined(AUTH_TLS) && AUTH_TLS==2
94   " tls"
95 #endif
96   ;
97
98 if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
99 if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
100 return g;
101 }
102
103 gstring *
104 route_show_supported(gstring * g)
105 {
106 uschar * b = US""               /* static-build router names */
107 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
108   " accept"
109 #endif
110 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
111   " dnslookup"
112 #endif
113 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
114   " ipliteral"
115 #endif
116 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
117   " iplookup"
118 #endif
119 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
120   " manualroute"
121 #endif
122 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
123   " redirect"
124 #endif
125 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
126   " queryprogram"
127 #endif
128   ;
129
130 uschar * d = US""               /* dynamic-module router names */
131 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
132   " accept"
133 #endif
134 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
135   " dnslookup"
136 #endif
137 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
138   " ipliteral"
139 #endif
140 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
141   " iplookup"
142 #endif
143 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
144   " manualroute"
145 #endif
146 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
147   " redirect"
148 #endif
149 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
150   " queryprogram"
151 #endif
152   ;
153
154 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
155 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
156 return g;
157 }
158
159 gstring *
160 transport_show_supported(gstring * g)
161 {
162 uschar * b = US""               /* static-build transportnames */
163 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
164   " appendfile"
165 # ifdef SUPPORT_MAILDIR
166     "/maildir"
167 # endif
168 # ifdef SUPPORT_MAILSTORE
169     "/mailstore"
170 # endif
171 # ifdef SUPPORT_MBX
172     "/mbx"
173 # endif
174 #endif
175 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
176   " autoreply"
177 #endif
178 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
179   " lmtp"
180 #endif
181 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
182   " pipe"
183 #endif
184 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
185   " queuefile"
186 #endif
187 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
188   " smtp"
189 #endif
190   ;
191
192 uschar * d = US""               /* dynamic-module transportnames */
193 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
194   " appendfile"
195 # ifdef SUPPORT_MAILDIR
196     "/maildir"
197 # endif
198 # ifdef SUPPORT_MAILSTORE
199     "/mailstore"
200 # endif
201 # ifdef SUPPORT_MBX
202     "/mbx"
203 # endif
204 #endif
205 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
206   " autoreply"
207 #endif
208 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
209   " lmtp"
210 #endif
211 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
212   " pipe"
213 #endif
214 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
215   " queuefile"
216 #endif
217 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
218   " smtp"
219 #endif
220   ;
221
222 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
223 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
224 return g;
225 }
226
227
228
229 static void
230 add_lookup_to_tree(lookup_info * li)
231 {
232 tree_node * new = store_get_perm(sizeof(tree_node) + Ustrlen(li->name),
233                                                         GET_UNTAINTED);
234 new->data.ptr = (void *)li;
235 Ustrcpy(new->name, li->name);
236 if (tree_insertnode(&lookups_tree, new))
237   li->acq_num = lookup_list_count++;
238 else
239   log_write(0, LOG_MAIN|LOG_PANIC, "Duplicate lookup name '%s'", li->name);
240 }
241
242
243 /* Add all the lookup types provided by the module */
244 static void
245 addlookupmodule(const struct lookup_module_info * lmi)
246 {
247 for (int j = 0; j < lmi->lookupcount; j++)
248   add_lookup_to_tree(lmi->lookups[j]);
249 }
250
251
252
253 /* Hunt for the lookup with the given acquisition number */
254
255 static unsigned hunt_acq;
256
257 static void
258 acq_cb(uschar * name, uschar * ptr, void * ctx)
259 {
260 lookup_info * li = (lookup_info *)ptr;
261 if (li->acq_num == hunt_acq) *(lookup_info **)ctx = li;
262 }
263
264 const lookup_info *
265 lookup_with_acq_num(unsigned k)
266 {
267 const lookup_info * li = NULL;
268 hunt_acq = k;
269 tree_walk(lookups_tree, acq_cb, &li);
270 return li;
271 }
272
273
274
275 /* These need to be at file level for old versions of gcc (2.95.2 reported),
276 which give parse errors on an extern in function scope.  Each entry needs
277 to also be invoked in init_lookup_list() below  */
278
279 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
280 extern lookup_module_info cdb_lookup_module_info;
281 #endif
282 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
283 extern lookup_module_info dbmdb_lookup_module_info;
284 #endif
285 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
286 extern lookup_module_info dnsdb_lookup_module_info;
287 #endif
288 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
289 extern lookup_module_info dsearch_lookup_module_info;
290 #endif
291 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
292 extern lookup_module_info ibase_lookup_module_info;
293 #endif
294 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
295 extern lookup_module_info json_lookup_module_info;
296 #endif
297 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
298 extern lookup_module_info ldap_lookup_module_info;
299 #endif
300 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
301 extern lookup_module_info lsearch_lookup_module_info;
302 #endif
303 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
304 extern lookup_module_info mysql_lookup_module_info;
305 #endif
306 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
307 extern lookup_module_info nis_lookup_module_info;
308 #endif
309 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
310 extern lookup_module_info nisplus_lookup_module_info;
311 #endif
312 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
313 extern lookup_module_info oracle_lookup_module_info;
314 #endif
315 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
316 extern lookup_module_info passwd_lookup_module_info;
317 #endif
318 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
319 extern lookup_module_info pgsql_lookup_module_info;
320 #endif
321 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
322 extern lookup_module_info redis_lookup_module_info;
323 #endif
324 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
325 extern lookup_module_info lmdb_lookup_module_info;
326 #endif
327 #if defined(SUPPORT_SPF)
328 extern lookup_module_info spf_lookup_module_info;
329 #endif
330 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
331 extern lookup_module_info sqlite_lookup_module_info;
332 #endif
333 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
334 extern lookup_module_info testdb_lookup_module_info;
335 #endif
336 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
337 extern lookup_module_info whoson_lookup_module_info;
338 #endif
339
340 extern lookup_module_info readsock_lookup_module_info;
341
342
343 #ifdef LOOKUP_MODULE_DIR
344 /* Try to load a lookup module with the given name.
345
346 Arguments:
347     name                name of the lookup
348     errstr              if not NULL, place "open fail" error message here
349
350 Return: boolean success
351 */
352
353 static BOOL
354 lookup_mod_load(const uschar * name, uschar ** errstr)
355 {
356 const uschar * path = string_sprintf(
357   LOOKUP_MODULE_DIR "/%s_lookup." DYNLIB_FN_EXT, name);
358 void * dl;
359 struct lookup_module_info * info;
360 const char * errormsg;
361
362 if (!(dl = dlopen(CS path, RTLD_NOW)))
363   {
364   if (errstr)
365     *errstr = string_sprintf("Error loading %s: %s", name, dlerror());
366   else
367     (void) dlerror();           /* clear out error state */
368   return FALSE;
369   }
370
371 /* FreeBSD nsdispatch() can trigger dlerror() errors about
372 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
373 state before calling dlsym(), so that any error afterwards only comes
374 from dlsym().  */
375
376 errormsg = dlerror();
377
378 info = (struct lookup_module_info *) dlsym(dl, "_lookup_module_info");
379 if ((errormsg = dlerror()))
380   {
381   fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
382   log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)", name, errormsg);
383   dlclose(dl);
384   return FALSE;
385   }
386 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
387   {
388   fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
389   log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim", name);
390   dlclose(dl);
391   return FALSE;
392   }
393
394 addlookupmodule(info);
395 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\" (%d lookup type%s)\n",
396                                     name, info->lookupcount,
397                                     info->lookupcount > 1 ? "s" : "");
398 return TRUE;
399 }
400
401
402 /* Try to load a lookup module, assuming the module name is the same
403 as the lookup type name.  This will only work for single-method modules.
404 Other have to be always-load (see the RE in init_lookup_list() below).
405 */
406
407 BOOL
408 lookup_one_mod_load(const uschar * name, uschar ** errstr)
409 {
410 if (!lookup_mod_load(name, errstr)) return FALSE;
411 /*XXX notify daemon? */
412 return TRUE;
413 }
414
415 #endif  /*LOOKUP_MODULE_DIR*/
416
417
418
419
420
421 void
422 init_lookup_list(void)
423 {
424 #ifdef LOOKUP_MODULE_DIR
425 DIR * dd;
426 int countmodules = 0;
427 #endif
428 static BOOL lookup_list_init_done = FALSE;
429
430 if (lookup_list_init_done)
431   return;
432 lookup_list_init_done = TRUE;
433
434 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
435 addlookupmodule(&cdb_lookup_module_info);
436 #endif
437
438 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
439 addlookupmodule(&dbmdb_lookup_module_info);
440 #endif
441
442 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
443 addlookupmodule(&dnsdb_lookup_module_info);
444 #endif
445
446 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
447 addlookupmodule(&dsearch_lookup_module_info);
448 #endif
449
450 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
451 addlookupmodule(&ibase_lookup_module_info);
452 #endif
453
454 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
455 addlookupmodule(&ldap_lookup_module_info);
456 #endif
457
458 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
459 addlookupmodule(&json_lookup_module_info);
460 #endif
461
462 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
463 addlookupmodule(&lsearch_lookup_module_info);
464 #endif
465
466 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
467 addlookupmodule(&mysql_lookup_module_info);
468 #endif
469
470 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
471 addlookupmodule(&nis_lookup_module_info);
472 #endif
473
474 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
475 addlookupmodule(&nisplus_lookup_module_info);
476 #endif
477
478 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
479 addlookupmodule(&oracle_lookup_module_info);
480 #endif
481
482 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
483 addlookupmodule(&passwd_lookup_module_info);
484 #endif
485
486 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
487 addlookupmodule(&pgsql_lookup_module_info);
488 #endif
489
490 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
491 addlookupmodule(&redis_lookup_module_info);
492 #endif
493
494 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
495 addlookupmodule(&lmdb_lookup_module_info);
496 #endif
497
498 #ifdef SUPPORT_SPF
499 addlookupmodule(&spf_lookup_module_info);
500 #endif
501
502 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
503 addlookupmodule(&sqlite_lookup_module_info);
504 #endif
505
506 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
507 addlookupmodule(&testdb_lookup_module_info);
508 #endif
509
510 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
511 addlookupmodule(&whoson_lookup_module_info);
512 #endif
513
514 /* This is a custom expansion, and not available as either
515 a list-syntax lookup or a lookup expansion. However, it is
516 implemented by a lookup module. */
517
518 addlookupmodule(&readsock_lookup_module_info);
519
520 DEBUG(D_lookup) debug_printf("Total %d built-in lookups\n", lookup_list_count);
521
522
523 #ifdef LOOKUP_MODULE_DIR
524 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
525   {
526   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
527   log_write(0, LOG_MAIN|LOG_PANIC,
528           "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
529   }
530 else
531   {
532   /* Look specifically for modules we know offer several lookup types and
533   load them now, since we cannot load-on-first-use. */
534
535   struct dirent * ent;
536   const pcre2_code * regex_islookupmod = regex_must_compile(
537     US"(lsearch|ldap|nis)_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
538
539   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
540   while ((ent = readdir(dd)))
541     {
542     char * name = ent->d_name;
543     int len = (int)strlen(name);
544     if (regex_match_and_setup(regex_islookupmod, US name, 0, 0))
545       {
546       uschar * errstr;
547       if (lookup_mod_load(expand_nstring[1], &errstr))
548         countmodules++;
549       else
550         {
551         fprintf(stderr, "%s\n", errstr);
552         log_write(0, LOG_MAIN|LOG_PANIC, "%s", errstr);
553         }
554       }
555     }
556   closedir(dd);
557   }
558
559 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
560 #endif
561
562
563 }
564
565
566 #endif  /*!MACRO_PREDEF*/
567 /* End of drtables.c */