ACL: "seen" condition
[exim.git] / src / src / dbstuff.h
index aec549f485932f689fabb0994c9928b61f2b2747..94db7f7fda92693f557bf685d2e795fd7e79389a 100644 (file)
@@ -2,7 +2,8 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* This header file contains macro definitions so that a variety of DBM
@@ -74,7 +75,7 @@ free() must not die when passed NULL */
         key.dptr != NULL)
 
 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
-#define EXIM_DBDELETE_CURSOR(cursor) free(cursor)
+#define EXIM_DBDELETE_CURSOR(cursor) store_free(cursor)
 
 /* EXIM_DBCLOSE */
 #define EXIM_DBCLOSE__(db)        tdb_close(db)
@@ -106,6 +107,10 @@ definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
 
 #ifdef DB_VERSION_STRING
 
+# if DB_VERSION_MAJOR >= 6
+#  error Version 6 and later BDB API is not supported
+# endif
+
 /* The API changed (again!) between the 2.x and 3.x versions */
 
 #if DB_VERSION_MAJOR >= 3
@@ -113,21 +118,21 @@ definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
 /***************** Berkeley db 3.x/4.x native definitions ******************/
 
 /* Basic DB type */
-#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
-# define EXIM_DB       DB_ENV
+# if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
+#  define EXIM_DB       DB_ENV
 /* Cursor type, for scanning */
-# define EXIM_CURSOR   DBC
+#  define EXIM_CURSOR   DBC
 
 /* The datum type used for queries */
-# define EXIM_DATUM    DBT
+#  define EXIM_DATUM    DBT
 
 /* Some text for messages */
-# define EXIM_DBTYPE   "db (v4.1+)"
+#  define EXIM_DBTYPE   "db (v4.1+)"
 
 /* Only more-recent versions.  5+ ? */
-# ifndef DB_FORCESYNC
-#  define DB_FORCESYNC 0
-# endif
+#  ifndef DB_FORCESYNC
+#   define DB_FORCESYNC 0
+#  endif
 
 
 /* Access functions */
@@ -136,9 +141,9 @@ definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
 API changed for DB 4.1. - and we also starting using the "env" with a
 specified working dir, to avoid the DBCONFIG file trap. */
 
-# define ENV_TO_DB(env) ((DB *)((env)->app_private))
+#  define ENV_TO_DB(env) ((DB *)((env)->app_private))
 
-# define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
+#  define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
   if (  db_env_create(dbpp, 0) != 0                                            \
      || ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), 0)              \
      || (*dbpp)->open(*dbpp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0\
@@ -161,72 +166,72 @@ specified working dir, to avoid the DBCONFIG file trap. */
     }
 
 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
-# define EXIM_DBGET(db, key, data)      \
+#  define EXIM_DBGET(db, key, data)      \
        (ENV_TO_DB(db)->get(ENV_TO_DB(db), NULL, &key, &data, 0) == 0)
 
 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
-# define EXIM_DBPUT(db, key, data)      \
+#  define EXIM_DBPUT(db, key, data)      \
        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, 0)
 
 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
-# define EXIM_DBPUTB(db, key, data)      \
+#  define EXIM_DBPUTB(db, key, data)      \
        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, DB_NOOVERWRITE)
 
 /* Return values from EXIM_DBPUTB */
 
-# define EXIM_DBPUTB_OK  0
-# define EXIM_DBPUTB_DUP DB_KEYEXIST
+#  define EXIM_DBPUTB_OK  0
+#  define EXIM_DBPUTB_DUP DB_KEYEXIST
 
 /* EXIM_DBDEL */
-# define EXIM_DBDEL(db, key)     ENV_TO_DB(db)->del(ENV_TO_DB(db), NULL, &key, 0)
+#  define EXIM_DBDEL(db, key)     ENV_TO_DB(db)->del(ENV_TO_DB(db), NULL, &key, 0)
 
 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
 
-# define EXIM_DBCREATE_CURSOR(db, cursor) \
+#  define EXIM_DBCREATE_CURSOR(db, cursor) \
        ENV_TO_DB(db)->cursor(ENV_TO_DB(db), NULL, cursor, 0)
 
 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
-# define EXIM_DBSCAN(db, key, data, first, cursor)      \
+#  define EXIM_DBSCAN(db, key, data, first, cursor)      \
        ((cursor)->c_get(cursor, &key, &data,         \
          (first? DB_FIRST : DB_NEXT)) == 0)
 
 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
-# define EXIM_DBDELETE_CURSOR(cursor) \
+#  define EXIM_DBDELETE_CURSOR(cursor) \
        (cursor)->c_close(cursor)
 
 /* EXIM_DBCLOSE */
-# define EXIM_DBCLOSE__(db) \
+#  define EXIM_DBCLOSE__(db) \
        (ENV_TO_DB(db)->close(ENV_TO_DB(db), 0) , ((DB_ENV *)(db))->close((DB_ENV *)(db), DB_FORCESYNC))
 
 /* Datum access types - these are intended to be assignable. */
 
-# define EXIM_DATUM_SIZE(datum)  (datum).size
-# define EXIM_DATUM_DATA(datum)  (datum).data
+#  define EXIM_DATUM_SIZE(datum)  (datum).size
+#  define EXIM_DATUM_DATA(datum)  (datum).data
 
 /* The whole datum structure contains other fields that must be cleared
 before use, but we don't have to free anything after reading data. */
 
-# define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
-# define EXIM_DATUM_FREE(datum)
+#  define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
+#  define EXIM_DATUM_FREE(datum)
 
-#else  /* pre- 4.1 */
+# else /* pre- 4.1 */
 
-# define EXIM_DB       DB
+#  define EXIM_DB       DB
 
 /* Cursor type, for scanning */
-# define EXIM_CURSOR   DBC
+#  define EXIM_CURSOR   DBC
 
 /* The datum type used for queries */
-# define EXIM_DATUM    DBT
+#  define EXIM_DATUM    DBT
 
 /* Some text for messages */
-# define EXIM_DBTYPE   "db (v3/4)"
+#  define EXIM_DBTYPE   "db (v3/4)"
 
 /* Access functions */
 
 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. */
 
-# define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
+#  define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
        if (db_create(dbpp, NULL, 0) != 0 || \
          ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
          ((*dbpp)->open)(*dbpp, CS name, NULL, \
@@ -235,54 +240,54 @@ before use, but we don't have to free anything after reading data. */
          mode)) != 0) *(dbpp) = NULL
 
 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
-# define EXIM_DBGET(db, key, data)      \
+#  define EXIM_DBGET(db, key, data)      \
        ((db)->get(db, NULL, &key, &data, 0) == 0)
 
 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
-# define EXIM_DBPUT(db, key, data)      \
+#  define EXIM_DBPUT(db, key, data)      \
        (db)->put(db, NULL, &key, &data, 0)
 
 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
-# define EXIM_DBPUTB(db, key, data)      \
+#  define EXIM_DBPUTB(db, key, data)      \
        (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
 
 /* Return values from EXIM_DBPUTB */
 
-# define EXIM_DBPUTB_OK  0
-# define EXIM_DBPUTB_DUP DB_KEYEXIST
+#  define EXIM_DBPUTB_OK  0
+#  define EXIM_DBPUTB_DUP DB_KEYEXIST
 
 /* EXIM_DBDEL */
-# define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
+#  define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
 
 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
 
-# define EXIM_DBCREATE_CURSOR(db, cursor) \
+#  define EXIM_DBCREATE_CURSOR(db, cursor) \
        (db)->cursor(db, NULL, cursor, 0)
 
 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
-# define EXIM_DBSCAN(db, key, data, first, cursor)      \
+#  define EXIM_DBSCAN(db, key, data, first, cursor)      \
        ((cursor)->c_get(cursor, &key, &data,         \
          (first? DB_FIRST : DB_NEXT)) == 0)
 
 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
-# define EXIM_DBDELETE_CURSOR(cursor) \
+#  define EXIM_DBDELETE_CURSOR(cursor) \
        (cursor)->c_close(cursor)
 
 /* EXIM_DBCLOSE */
-# define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
+#  define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
 
 /* Datum access types - these are intended to be assignable. */
 
-# define EXIM_DATUM_SIZE(datum)  (datum).size
-# define EXIM_DATUM_DATA(datum)  (datum).data
+#  define EXIM_DATUM_SIZE(datum)  (datum).size
+#  define EXIM_DATUM_DATA(datum)  (datum).data
 
 /* The whole datum structure contains other fields that must be cleared
 before use, but we don't have to free anything after reading data. */
 
-# define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
-# define EXIM_DATUM_FREE(datum)
+#  define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
+#  define EXIM_DATUM_FREE(datum)
 
-#endif
+# endif
 
 
 #else /* DB_VERSION_MAJOR >= 3 */
@@ -431,9 +436,8 @@ before been able to pass successfully. */
 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
        ((db)->seq(db, &key, &data, (first? R_FIRST : R_NEXT)) == 0)
 
-/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
-refer to cursor, to keep picky compilers happy. */
-#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
+/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
+#define EXIM_DBDELETE_CURSOR(cursor) { }
 
 /* EXIM_DBCLOSE */
 #define EXIM_DBCLOSE__(db)        (db)->close(db)
@@ -519,9 +523,8 @@ typedef struct {
     (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
     db->lkey = key, key.dptr != NULL)
 
-/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
-refer to cursor, to keep picky compilers happy. */
-#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
+/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
+#define EXIM_DBDELETE_CURSOR(cursor) { }
 
 /* EXIM_DBCLOSE */
 #define EXIM_DBCLOSE__(db) \
@@ -597,9 +600,8 @@ interface */
 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
        (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
 
-/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). Make it
-refer to cursor, to keep picky compilers happy. */
-#define EXIM_DBDELETE_CURSOR(cursor) { cursor = cursor; }
+/* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
+#define EXIM_DBDELETE_CURSOR(cursor) { }
 
 /* EXIM_DBCLOSE */
 #define EXIM_DBCLOSE__(db) dbm_close(db)
@@ -632,14 +634,22 @@ after reading data. */
 #  define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
   do { \
   DEBUG(D_hints_lookup) \
-    debug_printf("EXIM_DBOPEN: file <%s> dir <%s> flags 0x%x\n", \
-      (name), (dirname), flags); \
-  EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); \
-  DEBUG(D_hints_lookup) debug_printf("returned from EXIM_DBOPEN: %p\n", *dbpp); \
+    debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n", \
+      (name), (dirname),               \
+      (flags) == O_RDONLY ? "O_RDONLY" \
+      : (flags) == O_RDWR ? "O_RDWR"   \
+      : (flags) == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT" \
+      : "??"); \
+  if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB file not permitted", name) \
+      || is_tainted2(dirname, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB directory not permitted", dirname)) \
+    *dbpp = NULL; \
+  else \
+    { EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); } \
+  DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", *dbpp); \
   } while(0)
 #  define EXIM_DBCLOSE(db) \
   do { \
-  DEBUG(D_hints_lookup) debug_printf("EXIM_DBCLOSE(%p)\n", db); \
+  DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", db); \
   EXIM_DBCLOSE__(db); \
   } while(0)
 
@@ -779,4 +789,44 @@ typedef struct {
 } dbdata_ratelimit_unique;
 
 
+/* For "seen" ACL condition */
+typedef struct {
+  time_t time_stamp;
+} dbdata_seen;
+
+#ifndef DISABLE_PIPE_CONNECT
+/* This structure records the EHLO responses, cleartext and crypted,
+for an IP, as bitmasks (cf. OPTION_TLS).  For LIMITS, also values
+advertised for MAILMAX, RCPTMAX and RCPTDOMAINMAX; zero meaning no
+value advertised. */
+
+typedef struct {
+  unsigned short cleartext_features;
+  unsigned short crypted_features;
+  unsigned short cleartext_auths;
+  unsigned short crypted_auths;
+
+# ifdef EXPERIMENTAL_ESMTP_LIMITS
+  unsigned int limit_mail;
+  unsigned int limit_rcpt;
+  unsigned int limit_rcptdom;
+# endif
+} ehlo_resp_precis;
+
+typedef struct {
+  time_t time_stamp;
+  /*************/
+  ehlo_resp_precis data;
+} dbdata_ehlo_resp;
+#endif
+
+typedef struct {
+  time_t time_stamp;
+  /*************/
+  uschar verify_override:1;
+  uschar ocsp:3;
+  uschar session[1];
+} dbdata_tls_session;
+
+
 /* End of dbstuff.h */