1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
7 /* See the file NOTICE for conditions of use and distribution. */
9 /* This header file contains macro definitions so that a variety of DBM
10 libraries can be used by Exim. Nigel Metheringham provided the original set for
11 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
12 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
13 James Antill. Most recently, support for native mode gdbm was added, with code
14 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
16 For convenience, the definitions of the structures used in the various hints
17 databases are also kept in this file, which is used by the maintenance
18 utilities as well as the main Exim binary. */
23 /* ************************* tdb interface ************************ */
28 # define EXIM_DB TDB_CONTEXT
30 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
31 tdb_traverse to be called) */
32 # define EXIM_CURSOR TDB_DATA
34 /* The datum type used for queries */
35 # define EXIM_DATUM TDB_DATA
37 /* Some text for messages */
38 # define EXIM_DBTYPE "tdb"
40 /* Access functions */
42 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
43 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
44 *(dbpp) = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode)
46 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
47 # define EXIM_DBGET(db, key, data) \
48 (data = tdb_fetch(db, key), data.dptr != NULL)
50 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
51 # define EXIM_DBPUT(db, key, data) \
52 tdb_store(db, key, data, TDB_REPLACE)
54 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
55 # define EXIM_DBPUTB(db, key, data) \
56 tdb_store(db, key, data, TDB_INSERT)
58 /* Returns from EXIM_DBPUTB */
60 # define EXIM_DBPUTB_OK 0
61 # define EXIM_DBPUTB_DUP (-1)
64 # define EXIM_DBDEL(db, key) tdb_delete(db, key)
66 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
67 # define EXIM_DBCREATE_CURSOR(db, cursor) { \
68 *(cursor) = store_malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
70 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
71 free() must not die when passed NULL */
72 # define EXIM_DBSCAN(db, key, data, first, cursor) \
73 (key = (first ? tdb_firstkey(db) : tdb_nextkey(db, *(cursor))), \
74 free((cursor)->dptr), *(cursor) = key, \
77 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
78 # define EXIM_DBDELETE_CURSOR(cursor) store_free(cursor)
81 # define EXIM_DBCLOSE__(db) tdb_close(db)
83 /* Datum access types - these are intended to be assignable */
85 # define EXIM_DATUM_SIZE(datum) (datum).dsize
86 # define EXIM_DATUM_DATA(datum) (datum).dptr
88 /* Free the stuff inside the datum. */
90 # define EXIM_DATUM_FREE(datum) (free((datum).dptr), (datum).dptr = NULL)
92 /* No initialization is needed. */
94 # define EXIM_DATUM_INIT(datum)
98 # define EXIM_DB_RLIMIT 150
105 /********************* Berkeley db native definitions **********************/
112 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
113 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
115 # ifdef DB_VERSION_STRING
117 # if DB_VERSION_MAJOR >= 6
118 # error Version 6 and later BDB API is not supported
121 /* The API changed (again!) between the 2.x and 3.x versions */
123 # if DB_VERSION_MAJOR >= 3
125 /***************** Berkeley db 3.x/4.x native definitions ******************/
128 # if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
129 # define EXIM_DB DB_ENV
130 /* Cursor type, for scanning */
131 # define EXIM_CURSOR DBC
133 /* The datum type used for queries */
134 # define EXIM_DATUM DBT
136 /* Some text for messages */
137 # define EXIM_DBTYPE "db (v4.1+)"
139 /* Only more-recent versions. 5+ ? */
140 # ifndef DB_FORCESYNC
141 # define DB_FORCESYNC 0
145 /* Access functions */
147 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
148 API changed for DB 4.1. - and we also starting using the "env" with a
149 specified working dir, to avoid the DBCONFIG file trap. */
151 # define ENV_TO_DB(env) ((DB *)((env)->app_private))
153 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
154 if ( db_env_create(dbpp, 0) != 0 \
155 || ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), 0) \
156 || (*dbpp)->open(*dbpp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0\
159 else if (db_create((DB **) &((*dbpp)->app_private), *dbpp, 0) != 0) \
161 ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0); \
164 else if (ENV_TO_DB(*dbpp)->open(ENV_TO_DB(*dbpp), NULL, CS name, NULL, \
165 (flags) == O_RDONLY ? DB_UNKNOWN : DB_HASH, \
166 (flags) == O_RDONLY ? DB_RDONLY : DB_CREATE, \
170 ENV_TO_DB(*dbpp)->close(ENV_TO_DB(*dbpp), 0); \
171 ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0); \
175 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
176 # define EXIM_DBGET(db, key, data) \
177 (ENV_TO_DB(db)->get(ENV_TO_DB(db), NULL, &key, &data, 0) == 0)
179 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
180 # define EXIM_DBPUT(db, key, data) \
181 ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, 0)
183 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
184 # define EXIM_DBPUTB(db, key, data) \
185 ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, DB_NOOVERWRITE)
187 /* Return values from EXIM_DBPUTB */
189 # define EXIM_DBPUTB_OK 0
190 # define EXIM_DBPUTB_DUP DB_KEYEXIST
193 # define EXIM_DBDEL(db, key) ENV_TO_DB(db)->del(ENV_TO_DB(db), NULL, &key, 0)
195 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
197 # define EXIM_DBCREATE_CURSOR(db, cursor) \
198 ENV_TO_DB(db)->cursor(ENV_TO_DB(db), NULL, cursor, 0)
200 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
201 # define EXIM_DBSCAN(db, key, data, first, cursor) \
202 ((cursor)->c_get(cursor, &key, &data, \
203 (first? DB_FIRST : DB_NEXT)) == 0)
205 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
206 # define EXIM_DBDELETE_CURSOR(cursor) \
207 (cursor)->c_close(cursor)
210 # define EXIM_DBCLOSE__(db) \
211 (ENV_TO_DB(db)->close(ENV_TO_DB(db), 0) , ((DB_ENV *)(db))->close((DB_ENV *)(db), DB_FORCESYNC))
213 /* Datum access types - these are intended to be assignable. */
215 # define EXIM_DATUM_SIZE(datum) (datum).size
216 # define EXIM_DATUM_DATA(datum) (datum).data
218 /* The whole datum structure contains other fields that must be cleared
219 before use, but we don't have to free anything after reading data. */
221 # define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
222 # define EXIM_DATUM_FREE(datum)
224 # else /* pre- 4.1 */
228 /* Cursor type, for scanning */
229 # define EXIM_CURSOR DBC
231 /* The datum type used for queries */
232 # define EXIM_DATUM DBT
234 /* Some text for messages */
235 # define EXIM_DBTYPE "db (v3/4)"
237 /* Access functions */
239 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. */
241 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
242 if (db_create(dbpp, NULL, 0) != 0 || \
243 ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
244 ((*dbpp)->open)(*dbpp, CS name, NULL, \
245 ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
246 ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
247 mode)) != 0) *(dbpp) = NULL
249 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
250 # define EXIM_DBGET(db, key, data) \
251 ((db)->get(db, NULL, &key, &data, 0) == 0)
253 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
254 # define EXIM_DBPUT(db, key, data) \
255 (db)->put(db, NULL, &key, &data, 0)
257 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
258 # define EXIM_DBPUTB(db, key, data) \
259 (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
261 /* Return values from EXIM_DBPUTB */
263 # define EXIM_DBPUTB_OK 0
264 # define EXIM_DBPUTB_DUP DB_KEYEXIST
267 # define EXIM_DBDEL(db, key) (db)->del(db, NULL, &key, 0)
269 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
271 # define EXIM_DBCREATE_CURSOR(db, cursor) \
272 (db)->cursor(db, NULL, cursor, 0)
274 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
275 # define EXIM_DBSCAN(db, key, data, first, cursor) \
276 ((cursor)->c_get(cursor, &key, &data, \
277 (first? DB_FIRST : DB_NEXT)) == 0)
279 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
280 # define EXIM_DBDELETE_CURSOR(cursor) \
281 (cursor)->c_close(cursor)
284 # define EXIM_DBCLOSE__(db) (db)->close(db, 0)
286 /* Datum access types - these are intended to be assignable. */
288 # define EXIM_DATUM_SIZE(datum) (datum).size
289 # define EXIM_DATUM_DATA(datum) (datum).data
291 /* The whole datum structure contains other fields that must be cleared
292 before use, but we don't have to free anything after reading data. */
294 # define EXIM_DATUM_INIT(datum) memset(&datum, 0, sizeof(datum))
295 # define EXIM_DATUM_FREE(datum)
300 # else /* DB_VERSION_MAJOR >= 3 */
301 # error Berkeley DB versions earlier than 3 are not supported */
302 # endif /* DB_VERSION_MAJOR */
303 # endif /* DB_VERSION_STRING */
306 /* all BDB versions */
309 # define EXIM_DB_RLIMIT 150
316 /********************* gdbm interface definitions **********************/
318 #elif defined USE_GDBM
324 GDBM_FILE gdbm; /* Database */
325 datum lkey; /* Last key, for scans */
328 /* Cursor type, not used with gdbm: just set up a dummy */
329 # define EXIM_CURSOR int
331 /* The datum type used for queries */
332 # define EXIM_DATUM datum
334 /* Some text for messages */
336 # define EXIM_DBTYPE "gdbm"
338 /* Access functions */
340 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
341 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
342 { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
343 if (*(dbpp) != NULL) { \
344 (*(dbpp))->lkey.dptr = NULL;\
345 (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
346 if ((*(dbpp))->gdbm == NULL) {\
353 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
354 # define EXIM_DBGET(db, key, data) \
355 (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
357 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
358 # define EXIM_DBPUT(db, key, data) \
359 gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
361 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
362 # define EXIM_DBPUTB(db, key, data) \
363 gdbm_store(db->gdbm, key, data, GDBM_INSERT)
365 /* Returns from EXIM_DBPUTB */
367 # define EXIM_DBPUTB_OK 0
368 # define EXIM_DBPUTB_DUP 1
371 # define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
373 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
374 # define EXIM_DBCREATE_CURSOR(db, cursor) {}
377 # define EXIM_DBSCAN(db, key, data, first, cursor) \
378 ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
379 (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
380 db->lkey = key, key.dptr != NULL)
382 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
383 # define EXIM_DBDELETE_CURSOR(cursor) { }
386 # define EXIM_DBCLOSE__(db) \
387 { gdbm_close((db)->gdbm);\
388 if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
391 /* Datum access types - these are intended to be assignable */
393 # define EXIM_DATUM_SIZE(datum) (datum).dsize
394 # define EXIM_DATUM_DATA(datum) (datum).dptr
396 /* There's no clearing required before use, but we have to free the dptr
397 after reading data. */
399 # define EXIM_DATUM_INIT(datum)
400 # define EXIM_DATUM_FREE(datum) free(datum.dptr)
404 # define EXIM_DB_RLIMIT 150
413 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
417 /********************* ndbm interface definitions **********************/
424 /* Cursor type, not used with ndbm: just set up a dummy */
425 # define EXIM_CURSOR int
427 /* The datum type used for queries */
428 # define EXIM_DATUM datum
430 /* Some text for messages */
432 # define EXIM_DBTYPE "ndbm"
434 /* Access functions */
436 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
437 /* Check that the name given is not present. This catches
438 a directory name; otherwise we would create the name.pag and
439 name.dir files in the directory's parent. */
441 # define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
444 *(dbpp) = !(flags & O_CREAT) \
445 || lstat(CCS (name), &st) != 0 && errno == ENOENT \
446 ? dbm_open(CS (name), (flags), (mode)) \
447 : (errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST, \
451 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
452 # define EXIM_DBGET(db, key, data) \
453 (data = dbm_fetch(db, key), data.dptr != NULL)
455 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
456 # define EXIM_DBPUT(db, key, data) \
457 dbm_store(db, key, data, DBM_REPLACE)
459 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
460 # define EXIM_DBPUTB(db, key, data) \
461 dbm_store(db, key, data, DBM_INSERT)
463 /* Returns from EXIM_DBPUTB */
465 # define EXIM_DBPUTB_OK 0
466 # define EXIM_DBPUTB_DUP 1
469 # define EXIM_DBDEL(db, key) dbm_delete(db, key)
471 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
472 # define EXIM_DBCREATE_CURSOR(db, cursor) {}
475 # define EXIM_DBSCAN(db, key, data, first, cursor) \
476 (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
478 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
479 # define EXIM_DBDELETE_CURSOR(cursor) { }
482 # define EXIM_DBCLOSE__(db) dbm_close(db)
484 /* Datum access types - these are intended to be assignable */
486 # define EXIM_DATUM_SIZE(datum) (datum).dsize
487 # define EXIM_DATUM_DATA(datum) (datum).dptr
489 /* There's no clearing required before use, and we don't have to free anything
490 after reading data. */
492 # define EXIM_DATUM_INIT(datum)
493 # define EXIM_DATUM_FREE(datum)
497 # define EXIM_DB_RLIMIT 150
499 #endif /* USE_GDBM */
505 #ifdef COMPILE_UTILITY
507 # define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
508 EXIM_DBOPEN__(name, dirname, flags, mode, dbpp)
509 # define EXIM_DBCLOSE(db) EXIM_DBCLOSE__(db)
513 # define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
515 DEBUG(D_hints_lookup) \
516 debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n", \
518 (flags) == O_RDONLY ? "O_RDONLY" \
519 : (flags) == O_RDWR ? "O_RDWR" \
520 : (flags) == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT" \
522 if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB file not permitted", name) \
523 || is_tainted2(dirname, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB directory not permitted", dirname)) \
526 { EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); } \
527 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", *dbpp); \
529 # define EXIM_DBCLOSE(db) \
531 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", db); \
532 EXIM_DBCLOSE__(db); \
538 # define EXIM_DB void /* dummy */
541 # define EXIM_CURSOR void /* dummy */
543 /********************* End of dbm library definitions **********************/
546 /* Structure for carrying around an open DBM file, and an open locking file
547 that relates to it. */
555 /* Structures for records stored in exim database dbm files. They all
556 start with the same fields, described in the generic type. */
560 time_t time_stamp; /* Timestamp of writing */
564 /* This structure keeps track of retry information for a host or a local
570 time_t first_failed; /* Time of first failure */
571 time_t last_try; /* Time of last try */
572 time_t next_try; /* Time of next try */
573 BOOL expired; /* Retry time has expired */
574 int basic_errno; /* Errno of last failure */
575 int more_errno; /* Additional information */
576 uschar text[1]; /* Text message for last failure */
579 /* These structures keep track of addresses that have had callout verification
580 performed on them. There are two groups of records:
582 1. keyed by localpart@domain -
583 Full address was tested and record holds result
586 Domain response upto MAIL FROM:<>, postmaster, random local part;
588 If a record exists, the result field is either ccache_accept or ccache_reject,
589 or, for a domain record only, ccache_reject_mfnull when MAIL FROM:<> was
590 rejected. The other fields, however, (which are only relevant to domain
591 records) may also contain ccache_unknown if that particular test has not been
594 Originally, there was only one structure, used for both types. However, it got
595 expanded for domain records, so it got split. To make it possible for Exim to
596 handle the old type of record, we retain the old definition. The different
597 kinds of record can be distinguished by their different lengths. */
603 int postmaster_result; /* Postmaster is accepted */
604 int random_result; /* Random local part was accepted */
605 } dbdata_callout_cache_obs;
608 time_t time_stamp; /* Timestamp of last address check */
610 int result; /* accept or reject */
611 } dbdata_callout_cache_address;
613 /* For this new layout, we put the additional fields (the timestamps)
614 last so that if somebody reverts to an older Exim, the new records will
615 still make sense because they match the old layout. */
618 time_t time_stamp; /* Time stamp of last connection */
620 int result; /* Domain reject or accept */
621 int postmaster_result; /* Postmaster result */
622 int random_result; /* Random result */
623 time_t postmaster_stamp; /* Timestamp of postmaster check */
624 time_t random_stamp; /* Timestamp of random check */
625 } dbdata_callout_cache;
627 /* This structure keeps track of messages that are waiting for a particular
628 host for a particular transport. */
633 int count; /* Count of message ids */
634 int sequence; /* Sequence for continued records */
635 uschar text[1]; /* One long character string */
639 /* The contents of the "misc" database are a mixture of different kinds of
640 record, as defined below. The keys used for a specific type all start with a
641 given string such as "etrn-" or "host-serialize-". */
644 /* This structure records a connection to a particular host, for the
645 purpose of serializing access to certain hosts. For possible future extension,
646 a field is defined for holding the count of connections, but it is not
647 at present in use. The same structure is used for recording a running ETRN
653 int count; /* Reserved for possible connection count */
657 /* This structure records the information required for the ratelimit
663 int time_usec; /* Fractional part of time, from gettimeofday() */
664 double rate; /* Smoothed sending rate at that time */
667 /* Same as above, plus a Bloom filter for uniquifying events. */
670 dbdata_ratelimit dbd;
671 time_t bloom_epoch; /* When the Bloom filter was last reset */
672 unsigned bloom_size; /* Number of bytes in the Bloom filter */
673 uschar bloom[40]; /* Bloom filter which may be larger than this */
674 } dbdata_ratelimit_unique;
677 /* For "seen" ACL condition */
682 #ifndef DISABLE_PIPE_CONNECT
683 /* This structure records the EHLO responses, cleartext and crypted,
684 for an IP, as bitmasks (cf. OPTION_TLS). For LIMITS, also values
685 advertised for MAILMAX, RCPTMAX and RCPTDOMAINMAX; zero meaning no
689 unsigned short cleartext_features;
690 unsigned short crypted_features;
691 unsigned short cleartext_auths;
692 unsigned short crypted_auths;
694 # ifdef EXPERIMENTAL_ESMTP_LIMITS
695 unsigned int limit_mail;
696 unsigned int limit_rcpt;
697 unsigned int limit_rcptdom;
704 ehlo_resp_precis data;
711 uschar verify_override:1;
714 } dbdata_tls_session;
717 /* End of dbstuff.h */