The &'single-key'& type requires the specification of a file in which to look,
and a single key to search for. The key must be a non-empty string for the
lookup to succeed. The lookup type determines how the file is searched.
+.new
+.cindex "tainted data" "single-key lookups"
+The file string may not be tainted
+.wen
.next
.cindex "query-style lookup" "definition of"
The &'query-style'& type accepts a generalized database query. No particular
queue stripchart, and set up data for the queue display window if the "full"
option is given. */
-void scan_spool_input(int full)
+void
+scan_spool_input(int full)
{
int i;
int subptr;
int count = 0;
int indexptr = 1;
queue_item *p;
-struct dirent *ent;
-DIR *dd;
uschar input_dir[256];
uschar subdirs[64];
for (i = 0; i < subdir_max; i++)
{
int subdirchar = subdirs[i]; /* 0 for main directory */
+ DIR *dd;
+ struct dirent *ent;
+
if (subdirchar != 0)
{
input_dir[subptr] = '/';
input_dir[subptr+1] = subdirchar;
}
- dd = opendir(CS input_dir);
- if (dd == NULL) continue;
+ if (!(dd = exim_opendir(input_dir))) continue;
- while ((ent = readdir(dd)) != NULL)
+ while ((ent = readdir(dd)))
{
uschar *name = US ent->d_name;
int len = Ustrlen(name);
but in a long queue it won't make much difference, and in a short queue it
doesn't matter anyway!*/
-p = queue_index[0];
-while (p != NULL)
- {
+for (p = queue_index[0]; p; )
if (!p->seen)
{
- queue_item *next = p->next;
- if (p->prev == NULL) queue_index[0] = next;
- else p->prev->next = next;
- if (next == NULL)
+ queue_item * next = p->next;
+ if (p->prev)
+ p->prev->next = next;
+ else
+ queue_index[0] = next;
+ if (next)
+ next->prev = p->prev;
+ else
{
int i;
- queue_item *q = queue_index[queue_index_size-1];
+ queue_item * q = queue_index[queue_index_size-1];
for (i = queue_index_size - 1; i >= 0; i--)
if (queue_index[i] == q) queue_index[i] = p->prev;
}
- else next->prev = p->prev;
clean_up(p);
queue_total--;
p = next;
else
{
if (++count > (queue_total * indexptr)/(queue_index_size-1))
- {
queue_index[indexptr++] = p;
- }
p->seen = FALSE; /* for next time */
p = p->next;
}
- }
/* If a lot of messages have been removed at the bottom, we may not
have got the index all filled in yet. Make sure all the pointers
are legal. */
while (indexptr < queue_index_size - 1)
- {
queue_index[indexptr++] = queue_index[queue_index_size-1];
- }
}
if (created && geteuid() == root_uid)
{
- DIR *dd;
- struct dirent *ent;
+ DIR * dd;
uschar *lastname = Ustrrchr(filename, '/') + 1;
int namelen = Ustrlen(name);
*lastname = 0;
- dd = opendir(CS filename);
- while ((ent = readdir(dd)))
- if (Ustrncmp(ent->d_name, name, namelen) == 0)
- {
- struct stat statbuf;
- /* Filenames from readdir() are trusted, so use a taint-nonchecking copy */
- strcpy(CS lastname, CCS ent->d_name);
- if (Ustat(filename, &statbuf) >= 0 && statbuf.st_uid != exim_uid)
- {
- DEBUG(D_hints_lookup) debug_printf_indent("ensuring %s is owned by exim\n", filename);
- if (exim_chown(filename, exim_uid, exim_gid))
- DEBUG(D_hints_lookup) debug_printf_indent("failed setting %s to owned by exim\n", filename);
- }
- }
+ if ((dd = exim_opendir(filename)))
+ for (struct dirent *ent; ent = readdir(dd); )
+ if (Ustrncmp(ent->d_name, name, namelen) == 0)
+ {
+ struct stat statbuf;
+ /* Filenames from readdir() are trusted,
+ so use a taint-nonchecking copy */
+ strcpy(CS lastname, CCS ent->d_name);
+ if (Ustat(filename, &statbuf) >= 0 && statbuf.st_uid != exim_uid)
+ {
+ DEBUG(D_hints_lookup)
+ debug_printf_indent("ensuring %s is owned by exim\n", filename);
+ if (exim_chown(filename, exim_uid, exim_gid))
+ DEBUG(D_hints_lookup)
+ debug_printf_indent("failed setting %s to owned by exim\n", filename);
+ }
+ }
closedir(dd);
}
#endif
#ifdef LOOKUP_MODULE_DIR
-if (!(dd = opendir(LOOKUP_MODULE_DIR)))
+if (!(dd = exim_opendir(LOOKUP_MODULE_DIR)))
{
DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
exim_open2(const char *pathname, int flags)
{
if (!is_tainted(pathname)) return open(pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
errno = EACCES;
return -1;
}
exim_open(const char *pathname, int flags, mode_t mode)
{
if (!is_tainted(pathname)) return open(pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
errno = EACCES;
return -1;
}
exim_openat(int dirfd, const char *pathname, int flags)
{
if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
errno = EACCES;
return -1;
}
exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
{
if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
errno = EACCES;
return -1;
}
exim_fopen(const char *pathname, const char *mode)
{
if (!is_tainted(pathname)) return fopen(pathname, mode);
-log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
+errno = EACCES;
+return NULL;
+}
+
+static inline DIR *
+exim_opendir(const uschar * name)
+{
+if (!is_tainted(name)) return opendir(CCS name);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
errno = EACCES;
return NULL;
}
static void *
dsearch_open(uschar *dirname, uschar **errmsg)
{
-DIR *dp = opendir(CS dirname);
+DIR * dp = exim_opendir(dirname);
if (!dp)
{
int save_errno = errno;
int subptr;
queue_filename *yield = NULL;
queue_filename *last = NULL;
-struct dirent *ent;
-DIR *dd;
uschar buffer[256];
queue_filename *root[LOG2_MAXNODES];
{
int count = 0;
int subdirchar = subdirs[i]; /* 0 for main directory */
+ DIR *dd;
if (subdirchar != 0)
{
}
DEBUG(D_queue_run) debug_printf("looking in %s\n", buffer);
- if (!(dd = opendir(CS buffer)))
+ if (!(dd = exim_opendir(buffer)))
continue;
/* Now scan the directory. */
- while ((ent = readdir(dd)))
+ for (struct dirent *ent; ent = readdir(dd); )
{
uschar *name = US ent->d_name;
int len = Ustrlen(name);
struct dirent * entry;
DIR * tempdir;
- for (tempdir = opendir(CS scandir); entry = readdir(tempdir); )
+ for (tempdir = exim_opendir(scandir); entry = readdir(tempdir); )
if (strncmpic(US entry->d_name, US"__rfc822_", 9) == 0)
{
rfc822_file_path = string_sprintf("%s/%s", scandir, entry->d_name);
uschar keybuffer[256];
int old_pool = store_pool;
+if (filename && is_tainted(filename))
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "Tainted filename for search: '%s'", filename);
+ return NULL;
+ }
+
/* Change to the search store pool and remember our reset point */
store_pool = POOL_SEARCH;
if ((t = tree_search(search_tree, keybuffer)))
{
- c = (search_cache *)(t->data.ptr);
- if (c->handle)
+ if ((c = (search_cache *)t->data.ptr)->handle)
{
DEBUG(D_lookup) debug_printf_indent(" cached open\n");
store_pool = old_pool;
recently used one. */
if (lk->type == lookup_absfile && open_filecount >= lookup_open_max)
- {
if (!open_bot)
log_write(0, LOG_MAIN|LOG_PANIC, "too many lookups open, but can't find "
"one to close");
c->handle = NULL;
open_filecount--;
}
- }
/* If opening is successful, call the file-checking function if there is one,
and if all is still well, enter the open database into the tree. */
/* clean up old vacation log databases */
- oncelogdir=opendir(CS filter->vacation_directory);
-
- if (oncelogdir ==(DIR*)0 && errno != ENOENT)
+ if ( !(oncelogdir = exim_opendir(filter->vacation_directory))
+ && errno != ENOENT)
{
- filter->errmsg=CUS "unable to open vacation directory";
+ filter->errmsg = CUS "unable to open vacation directory";
return -1;
}
- if (oncelogdir != NULL)
+ if (oncelogdir)
{
time(&now);
- while ((oncelog=readdir(oncelogdir))!=(struct dirent*)0)
- {
+ while ((oncelog = readdir(oncelogdir)))
if (strlen(oncelog->d_name)==32)
{
- uschar *s=string_sprintf("%s/%s",filter->vacation_directory,oncelog->d_name);
+ uschar *s = string_sprintf("%s/%s",filter->vacation_directory,oncelog->d_name);
if (Ustat(s,&properties)==0 && (properties.st_mtime+VACATION_MAX_DAYS*86400)<now)
Uunlink(s);
}
- }
closedir(oncelogdir);
}
}
if (spool_mbox_ok && !f.no_mbox_unspool)
{
uschar *file_path;
- struct dirent *entry;
DIR *tempdir;
rmark reset_point = store_mark();
uschar * mbox_path = string_sprintf("%s/scan/%s", spool_directory, spooled_message_id);
- if (!(tempdir = opendir(CS mbox_path)))
+ if (!(tempdir = exim_opendir(mbox_path)))
{
debug_printf("Unable to opendir(%s): %s\n", mbox_path, strerror(errno));
/* Just in case we still can: */
return;
}
/* loop thru dir & delete entries */
- while((entry = readdir(tempdir)))
+ for (struct dirent *entry; entry = readdir(tempdir); )
{
uschar *name = US entry->d_name;
int dummy;
DIR *dir;
off_t sum = 0;
int count = *countptr;
-struct dirent *ent;
-struct stat statbuf;
-if (!(dir = opendir(CS dirname))) return 0;
+if (!(dir = exim_opendir(dirname))) return 0;
-while ((ent = readdir(dir)))
+for (struct dirent *ent; ent = readdir(dir); )
{
uschar * path, * name = US ent->d_name;
+ struct stat statbuf;
if (Ustrcmp(name, ".") == 0 || Ustrcmp(name, "..") == 0) continue;
{
DIR *dir;
off_t sum = 0;
-struct dirent *ent;
-struct stat statbuf;
-if (!(dir = opendir(CS path)))
+if (!(dir = exim_opendir(path)))
return 0;
-while ((ent = readdir(dir)))
+for (struct dirent *ent; ent = readdir(dir); )
{
uschar * s, * name = US ent->d_name;
+ struct stat statbuf;
if (Ustrcmp(name, ".") == 0 || Ustrcmp(name, "..") == 0) continue;
# ----- Main settings -----
+acl_not_smtp = accept set acl_m0 = ${lookup {key} dsearch {DIR/$recipients}}
+
# End
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 Tainted filename for search: 'TESTSUITE/tainted@test.ex'
+1999-03-02 09:44:33 10HmaX-0005vi-00 F=<CALLER@myhost.test.ex> rejected by non-SMTP ACL: failed to expand ACL string "accept set acl_m0 = ${lookup {key} dsearch {TESTSUITE/$recipients}}": NULL
+1999-03-02 09:44:33 10HmaY-0005vi-00 Tainted filename for search: 'TESTSUITE/CALLER@myhost.test.ex'
+1999-03-02 09:44:33 10HmaY-0005vi-00 F=<> rejected by non-SMTP ACL: failed to expand ACL string "accept set acl_m0 = ${lookup {key} dsearch {TESTSUITE/$recipients}}": NULL
+1999-03-02 09:44:33 10HmaY-0005vi-00 Error while reading message with no usable sender address (R=10HmaX-0005vi-00): rejected by non-SMTP ACL: local configuration problem
+1999-03-02 09:44:33 10HmaX-0005vi-00 Child mail process returned status 1
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 Tainted filename for search: 'TESTSUITE/tainted@test.ex'
+1999-03-02 09:44:33 10HmaY-0005vi-00 Tainted filename for search: 'TESTSUITE/CALLER@myhost.test.ex'
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 F=<CALLER@myhost.test.ex> rejected by non-SMTP ACL: failed to expand ACL string "accept set acl_m0 = ${lookup {key} dsearch {TESTSUITE/$recipients}}": NULL
+Envelope-from: <CALLER@myhost.test.ex>
+Envelope-to: <tainted@test.ex>
+P Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+ (envelope-from <CALLER@myhost.test.ex>)
+ id 10HmaX-0005vi-00
+ for tainted@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+I Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
+F From: CALLER_NAME <CALLER@myhost.test.ex>
+ Date: Tue, 2 Mar 1999 09:44:33 +0000
+1999-03-02 09:44:33 10HmaY-0005vi-00 F=<> rejected by non-SMTP ACL: failed to expand ACL string "accept set acl_m0 = ${lookup {key} dsearch {TESTSUITE/$recipients}}": NULL
+Envelope-from: <>
+Envelope-to: <CALLER@myhost.test.ex>
+P Received: from EXIMUSER by myhost.test.ex with local (Exim x.yz)
+ id 10HmaY-0005vi-00
+ for CALLER@myhost.test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+ Auto-Submitted: auto-replied
+F From: Mail Delivery System <Mailer-Daemon@myhost.test.ex>
+T To: CALLER@myhost.test.ex
+ References: <E10HmaX-0005vi-00@myhost.test.ex>
+ Subject: Mail failure - rejected by local scanning code
+I Message-Id: <E10HmaY-0005vi-00@myhost.test.ex>
+ Date: Tue, 2 Mar 1999 09:44:33 +0000
fail(case): ${lookup{TESTNUM.TST} dsearch{DIR/aux-fixed}{$value}{FAIL}}
fail(case): ${lookup{TESTNUM.TST} dsearch{DIR/AUX-fixed}{$value}{FAIL}}
****
+#
+1
+exim tainted@test.ex
+****
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 Tainted filename for search: 'TESTSUITE/tainted@test.ex'
+1999-03-02 09:44:33 10HmaY-0005vi-00 Tainted filename for search: 'TESTSUITE/CALLER@myhost.test.ex'