[exim-cvs] Sqlite: new main option sqlite_dbfile

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Sqlite: new main option sqlite_dbfile
Gitweb: https://git.exim.org/exim.git/commitdiff/298849d8ea217fd104d167f5233bd11240b3ddae
Commit:     298849d8ea217fd104d167f5233bd11240b3ddae
Parent:     3b447cdfe3f9f53546d09d7e01d1e0ecf0d6696c
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Wed Apr 1 23:29:40 2020 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Wed Apr 1 23:49:25 2020 +0100


    Sqlite: new main option sqlite_dbfile
---
 doc/doc-docbook/spec.xfpt     | 41 ++++++++++++++++++++++++++++++++---------
 doc/doc-txt/NewStuff          |  5 +++++
 doc/doc-txt/OptionLists.txt   |  1 +
 src/src/expand.c              | 17 +++++++----------
 src/src/globals.c             |  1 +
 src/src/globals.h             |  1 +
 src/src/lookups/sqlite.c      |  7 +++++--
 src/src/readconf.c            |  1 +
 test/confs/2600               |  3 +++
 test/scripts/2600-SQLite/2600 |  5 +++++
 test/stderr/2600              | 34 ++++++++++++++++++++++++----------
 test/stdout/2600              |  2 ++
 12 files changed, 87 insertions(+), 31 deletions(-)


diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index b9d73ad..bfe59fc 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -7029,7 +7029,11 @@ passed to a Redis database. See section &<<SECTsql>>&.
.next
.cindex "sqlite lookup type"
.cindex "lookup" "sqlite"
-&(sqlite)&: The format of the query is a filename followed by an SQL statement
+&(sqlite)&: The format of the query is
+new
+an optional filename
+.wen
+followed by an SQL statement
that is passed to an SQLite database. See section &<<SECTsqlite>>&.

 .next
@@ -7936,6 +7940,11 @@ If any MySQL, PostgreSQL, Oracle, InterBase or Redis lookups are used, the
 or &%redis_servers%&
 option (as appropriate) must be set to a colon-separated list of server
 information.
+.oindex &%mysql_servers%&
+.oindex &%pgsql_servers%&
+.oindex &%oracle_servers%&
+.oindex &%ibase_servers%&
+.oindex &%redis_servers%&
 (For MySQL and PostgreSQL, the global option need not be set if all
 queries contain their own server information &-- see section
 &<<SECTspeserque>>&.)
@@ -8073,17 +8082,31 @@ affected.
 .cindex "sqlite lookup type"
 SQLite is different to the other SQL lookups because a filename is required in
 addition to the SQL query. An SQLite database is a single file, and there is no
-daemon as in the other SQL databases. The interface to Exim requires the name
-of the file, as an absolute path, to be given at the start of the query. It is
-separated from the query by white space. This means that the path name cannot
-contain white space. Here is a lookup expansion example:
-.code
-${lookup sqlite {/some/thing/sqlitedb \
-  select name from aliases where id='userx';}}
+daemon as in the other SQL databases.
+
+.new
+.oindex &%sqlite_dbfile%&
+The preferred way of specifying the file is by using the 
+&%sqlite_dbfile%& option, set to
+.wen
+an absolute path.
+A deprecated method is available, prefixing the query with the filename
+separated by white space.
+This means that the path name cannot contain white space.
+.cindex "tainted data" "sqlite file"
+It also means that the query cannot use any tainted values, as that taints
+the entire query including the filename - resulting in a refusal to open
+the file.
+
+Here is a lookup expansion example:
+.code
+sqlite_dbfile = /some/thing/sqlitedb
+...
+${lookup sqlite {select name from aliases where id='userx';}}
 .endd
 In a list, the syntax is similar. For example:
 .code
-domainlist relay_to_domains = sqlite;/some/thing/sqlitedb \
+domainlist relay_to_domains = sqlite;\
    select * from relays where ip='$sender_host_address';
 .endd
 The only character affected by the &%quote_sqlite%& operator is a single
diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff
index fb6e444..62763e2 100644
--- a/doc/doc-txt/NewStuff
+++ b/doc/doc-txt/NewStuff
@@ -43,6 +43,11 @@ Version 4.94


11. New variables $local_part_{pre,suf}fix_v.

+12. New main option "sqlite_dbfile", for use in preference to prefixing the
+    lookup string.  The older method fails when tainted variables are used
+    in the lookup, as the filename becomes tainted.  The new method keeps the
+    filename separate.
+



 Version 4.93
diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt
index 717f87e..bb5a320 100644
--- a/doc/doc-txt/OptionLists.txt
+++ b/doc/doc-txt/OptionLists.txt
@@ -555,6 +555,7 @@ spamd_address                        string*         +             main
 split_spool_directory                boolean         false         main              1.70
 spool_directory                      string          ++            main
 spool_wireformat                     boolean         false         main              4.90
+sqlite_dbfile                        string*         unset         main              4.94 with LOOKUP_SQLITE
 sqlite_lock_timeout                  time            5s            main              4.53
 strict_acl_vars                      boolean         false         main              4.64
 srv_fail_domains                     domain list     unset         dnslookup         4.43
diff --git a/src/src/expand.c b/src/src/expand.c
index f937ac3..2366eb8 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -4892,16 +4892,13 @@ while (*s != 0)
         if (mac_islookup(stype, lookup_querystyle))
           filename = NULL;
         else
-          {
-          if (*filename != '/')
-            {
-            expand_string_message = string_sprintf(
-              "absolute file name expected for \"%s\" lookup", name);
-            goto EXPAND_FAILED;
-            }
-          while (*key != 0 && !isspace(*key)) key++;
-          if (*key != 0) *key++ = 0;
-          }
+          if (*filename == '/')
+        {
+        while (*key && !isspace(*key)) key++;
+        if (*key) *key++ = '\0';
+        }
+      else
+        filename = NULL;
         }


       /* If skipping, don't do the next bit - just lookup_value == NULL, as if
diff --git a/src/src/globals.c b/src/src/globals.c
index 57f857e..b8bf7ce 100644
--- a/src/src/globals.c
+++ b/src/src/globals.c
@@ -89,6 +89,7 @@ uschar *redis_servers          = NULL;
 #endif


 #ifdef LOOKUP_SQLITE
+uschar *sqlite_dbfile           = NULL;
 int     sqlite_lock_timeout    = 5;
 #endif


diff --git a/src/src/globals.h b/src/src/globals.h
index c922274..882f289 100644
--- a/src/src/globals.h
+++ b/src/src/globals.h
@@ -68,6 +68,7 @@ extern uschar *redis_servers;          /* List of servers and connect info */
 #endif


 #ifdef LOOKUP_SQLITE
+extern uschar *sqlite_dbfile;           /* Filname for database */
 extern int     sqlite_lock_timeout;    /* Internal lock waiting timeout */
 #endif


diff --git a/src/src/lookups/sqlite.c b/src/src/lookups/sqlite.c
index cf68b12..51d28c2 100644
--- a/src/src/lookups/sqlite.c
+++ b/src/src/lookups/sqlite.c
@@ -23,10 +23,13 @@ sqlite_open(const uschar * filename, uschar ** errmsg)
sqlite3 *db = NULL;
int ret;

-if ((ret = sqlite3_open(CCS filename, &db)) != 0)
+if (!filename || !*filename) filename = sqlite_dbfile;
+if (*filename != '/')
+ *errmsg = US"absolute file name expected for \"sqlite\" lookup";
+else if ((ret = sqlite3_open(CCS filename, &db)) != 0)
{
*errmsg = (void *)sqlite3_errmsg(db);
- debug_printf_indent("Error opening database: %s\n", *errmsg);
+ DEBUG(D_lookup) debug_printf_indent("Error opening database: %s\n", *errmsg);
}

 sqlite3_busy_timeout(db, 1000 * sqlite_lock_timeout);
diff --git a/src/src/readconf.c b/src/src/readconf.c
index 1243e90..2bf1e63 100644
--- a/src/src/readconf.c
+++ b/src/src/readconf.c
@@ -329,6 +329,7 @@ static optionlist optionlist_config[] = {
   { "spool_directory",          opt_stringptr,   {&spool_directory} },
   { "spool_wireformat",         opt_bool,        {&spool_wireformat} },
 #ifdef LOOKUP_SQLITE
+  { "sqlite_dbfile",            opt_stringptr,   {&sqlite_dbfile} },
   { "sqlite_lock_timeout",      opt_int,         {&sqlite_lock_timeout} },
 #endif
 #ifdef EXPERIMENTAL_SRS
diff --git a/test/confs/2600 b/test/confs/2600
index 566e260..e42cbe3 100644
--- a/test/confs/2600
+++ b/test/confs/2600
@@ -14,6 +14,9 @@ hostlist   relay_hosts = sqlite;DIR/aux-fixed/sqlitedb \
 acl_smtp_rcpt = check_recipient
 sqlite_lock_timeout = 2


+.ifdef DATA
+sqlite_dbfile = DATA
+.endif

# ----- ACL -----

diff --git a/test/scripts/2600-SQLite/2600 b/test/scripts/2600-SQLite/2600
index f388b1a..2a557a4 100644
--- a/test/scripts/2600-SQLite/2600
+++ b/test/scripts/2600-SQLite/2600
@@ -30,3 +30,8 @@ Test message
exim -d-all+lookup -be
${lookup sqlite{DIR/aux-fixed/sqlitedb select name from them where id='userx';}}
****
+#
+#
+exim -DDATA=DIR/aux-fixed/sqlitedb -d-all+lookup -be
+${lookup sqlite{select name from them where id='userx';}}
+****
diff --git a/test/stderr/2600 b/test/stderr/2600
index 15e9bb5..69e23f8 100644
--- a/test/stderr/2600
+++ b/test/stderr/2600
@@ -137,12 +137,12 @@ log directory space = nnnnnK inodes = nnnnn check_space = 10240K inodes = 100
SMTP>> 250 OK

SMTP<< rcpt to:<c@d>
using ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 23)
+processing "accept" (TESTSUITE/test-config 26)
check domains = +local_domains
d in "@"? no (end of list)
d in "+local_domains"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 24)
+processing "accept" (TESTSUITE/test-config 27)
check hosts = +relay_hosts
search_open: sqlite "TESTSUITE/aux-fixed/sqlitedb"
search_find: file="TESTSUITE/aux-fixed/sqlitedb"
@@ -157,7 +157,7 @@ lookup failed
host in "sqlite;TESTSUITE/aux-fixed/sqlitedb select * from them where id='10.0.0.0'"? no (end of list)
host in "+relay_hosts"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "deny" (TESTSUITE/test-config 25)
+processing "deny" (TESTSUITE/test-config 28)
message: relay not permitted
deny: condition test succeeded in ACL "check_recipient"
end of ACL "check_recipient": DENY
@@ -166,12 +166,12 @@ LOG: MAIN REJECT
H=[10.0.0.0] F=<a@b> rejected RCPT <c@d>: relay not permitted
SMTP<< rcpt to:<c@d>
using ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 23)
+processing "accept" (TESTSUITE/test-config 26)
check domains = +local_domains
d in "@"? no (end of list)
d in "+local_domains"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 24)
+processing "accept" (TESTSUITE/test-config 27)
check hosts = +relay_hosts
search_open: sqlite "TESTSUITE/aux-fixed/sqlitedb"
cached open
@@ -187,7 +187,7 @@ lookup failed
host in "sqlite;TESTSUITE/aux-fixed/sqlitedb select * from them where id='10.0.0.0'"? no (end of list)
host in "+relay_hosts"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "deny" (TESTSUITE/test-config 25)
+processing "deny" (TESTSUITE/test-config 28)
message: relay not permitted
deny: condition test succeeded in ACL "check_recipient"
end of ACL "check_recipient": DENY
@@ -232,12 +232,12 @@ log directory space = nnnnnK inodes = nnnnn check_space = 10240K inodes = 100
SMTP>> 250 OK

SMTP<< rcpt to:<c@d>
using ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 23)
+processing "accept" (TESTSUITE/test-config 26)
check domains = +local_domains
d in "@"? no (end of list)
d in "+local_domains"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 24)
+processing "accept" (TESTSUITE/test-config 27)
check hosts = +relay_hosts
search_open: sqlite "TESTSUITE/aux-fixed/sqlitedb"
search_find: file="TESTSUITE/aux-fixed/sqlitedb"
@@ -256,12 +256,12 @@ SMTP>> 250 Accepted
DSN: orcpt: NULL flags: 0
SMTP<< rcpt to:<c@d>
using ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 23)
+processing "accept" (TESTSUITE/test-config 26)
check domains = +local_domains
d in "@"? no (end of list)
d in "+local_domains"? no (end of list)
accept: condition test failed in ACL "check_recipient"
-processing "accept" (TESTSUITE/test-config 24)
+processing "accept" (TESTSUITE/test-config 27)
check hosts = +relay_hosts
search_open: sqlite "TESTSUITE/aux-fixed/sqlitedb"
cached open
@@ -489,3 +489,17 @@ dropping to exim gid; retaining priv uid
lookup yielded: Ayen Other
search_tidyup called
>>>>>>>>>>>>>>>> Exim pid=pppp (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>>

+Exim version x.yz ....
+configuration file is TESTSUITE/test-config
+admin user
+dropping to exim gid; retaining priv uid
+ search_open: sqlite "NULL"
+ search_find: file="NULL"
+ key="select name from them where id='userx';" partial=-1 affix=NULL starflags=0
+ LRU list:
+ internal_search_find: file="NULL"
+ type=sqlite key="select name from them where id='userx';"
+ database lookup required for select name from them where id='userx';
+ lookup yielded: Ayen Other
+search_tidyup called
+>>>>>>>>>>>>>>>> Exim pid=pppp (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>>
diff --git a/test/stdout/2600 b/test/stdout/2600
index 2b11b92..53d6b9b 100644
--- a/test/stdout/2600
+++ b/test/stdout/2600
@@ -32,3 +32,5 @@ after" id=newline
221 myhost.test.ex closing connection
> Ayen Other
>

+> Ayen Other
+>