0c3dd70491099e1a33be7c0960c2ea724fc07ef5
[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 void
344 init_lookup_list(void)
345 {
346 #ifdef LOOKUP_MODULE_DIR
347 DIR * dd;
348 struct dirent * ent;
349 int countmodules = 0;
350 int moduleerrors = 0;
351 #endif
352 static BOOL lookup_list_init_done = FALSE;
353
354 if (lookup_list_init_done)
355   return;
356 lookup_list_init_done = TRUE;
357
358 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
359 addlookupmodule(&cdb_lookup_module_info);
360 #endif
361
362 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
363 addlookupmodule(&dbmdb_lookup_module_info);
364 #endif
365
366 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
367 addlookupmodule(&dnsdb_lookup_module_info);
368 #endif
369
370 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
371 addlookupmodule(&dsearch_lookup_module_info);
372 #endif
373
374 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
375 addlookupmodule(&ibase_lookup_module_info);
376 #endif
377
378 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
379 addlookupmodule(&ldap_lookup_module_info);
380 #endif
381
382 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
383 addlookupmodule(&json_lookup_module_info);
384 #endif
385
386 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
387 addlookupmodule(&lsearch_lookup_module_info);
388 #endif
389
390 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
391 addlookupmodule(&mysql_lookup_module_info);
392 #endif
393
394 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
395 addlookupmodule(&nis_lookup_module_info);
396 #endif
397
398 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
399 addlookupmodule(&nisplus_lookup_module_info);
400 #endif
401
402 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
403 addlookupmodule(&oracle_lookup_module_info);
404 #endif
405
406 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
407 addlookupmodule(&passwd_lookup_module_info);
408 #endif
409
410 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
411 addlookupmodule(&pgsql_lookup_module_info);
412 #endif
413
414 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
415 addlookupmodule(&redis_lookup_module_info);
416 #endif
417
418 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
419 addlookupmodule(&lmdb_lookup_module_info);
420 #endif
421
422 #ifdef SUPPORT_SPF
423 addlookupmodule(&spf_lookup_module_info);
424 #endif
425
426 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
427 addlookupmodule(&sqlite_lookup_module_info);
428 #endif
429
430 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
431 addlookupmodule(&testdb_lookup_module_info);
432 #endif
433
434 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
435 addlookupmodule(&whoson_lookup_module_info);
436 #endif
437
438 /* This is a custom expansion, and not available as either
439 a list-syntax lookup or a lookup expansion. However, it is
440 implemented by a lookup module. */
441
442 addlookupmodule(&readsock_lookup_module_info);
443
444 #ifdef LOOKUP_MODULE_DIR
445 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
446   {
447   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
448   log_write(0, LOG_MAIN|LOG_PANIC,
449           "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
450   }
451 else
452   {
453   const pcre2_code * regex_islookupmod = regex_must_compile(
454     US"_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
455
456   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
457   while ((ent = readdir(dd)))
458     {
459     char * name = ent->d_name;
460     int len = (int)strlen(name);
461     if (regex_match(regex_islookupmod, US name, len, NULL))
462       {
463       int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
464       void *dl;
465       struct lookup_module_info *info;
466       const char *errormsg;
467
468       /* SRH: am I being paranoid here or what? */
469       if (pathnamelen > big_buffer_size)
470         {
471         fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
472         log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
473         continue;
474         }
475
476       /* SRH: snprintf here? */
477       sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
478
479       if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
480         {
481         errormsg = dlerror();
482         fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
483         log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
484         moduleerrors++;
485         continue;
486         }
487
488       /* FreeBSD nsdispatch() can trigger dlerror() errors about
489       _nss_cache_cycle_prevention_function; we need to clear the dlerror()
490       state before calling dlsym(), so that any error afterwards only comes
491       from dlsym().  */
492
493       errormsg = dlerror();
494
495       info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
496       if ((errormsg = dlerror()))
497         {
498         fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
499         log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
500         dlclose(dl);
501         moduleerrors++;
502         continue;
503         }
504       if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
505         {
506         fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
507         log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
508         dlclose(dl);
509         moduleerrors++;
510         continue;
511         }
512
513       addlookupmodule(info);
514       DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
515       countmodules++;
516       }
517     }
518   store_free((void*)regex_islookupmod);
519   closedir(dd);
520   }
521
522 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
523 #endif
524
525 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
526
527 }
528
529 #endif  /*!MACRO_PREDEF*/
530 /* End of drtables.c */