* Exim - an Internet mail transport agent *
*************************************************/
+/* Copyright (c) The Exim maintainers 2020 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* This module contains code for extracting addresses from a forwarding list
(from an alias or forward file) or by running the filter interpreter. It may do
*/
static uschar *
-rda_get_file_contents(redirect_block *rdata, int options, uschar **error,
+rda_get_file_contents(const redirect_block *rdata, int options, uschar **error,
int *yield)
{
FILE *fwd;
/* Reading a file is a form of expansion; we wish to deny attackers the
capability to specify the file name. */
-if ((*error = is_tainted2(filename, 0, "Tainted name '%s' for file read not permitted\n", filename)))
+if (is_tainted(filename))
{
+ *error = string_sprintf("Tainted name '%s' for file read not permitted\n",
+ filename);
*yield = FF_ERROR;
return NULL;
}
/* Read the file in one go in order to minimize the time we have it open. */
-filebuf = store_get(statbuf.st_size + 1, is_tainted(filename));
+filebuf = store_get(statbuf.st_size + 1, filename);
if (fread(filebuf, 1, statbuf.st_size, fwd) != statbuf.st_size)
{
*/
static int
-rda_extract(redirect_block *rdata, int options, uschar *include_directory,
- uschar *sieve_vacation_directory, uschar *sieve_enotify_mailto_owner,
- uschar *sieve_useraddress, uschar *sieve_subaddress,
- address_item **generated, uschar **error, error_block **eblockp,
- int *filtertype)
+rda_extract(const redirect_block * rdata, int options,
+ const uschar * include_directory, const uschar * sieve_vacation_directory,
+ const uschar * sieve_enotify_mailto_owner, const uschar * sieve_useraddress,
+ const uschar * sieve_subaddress, address_item ** generated, uschar ** error,
+ error_block ** eblockp, int * filtertype)
{
-uschar *data;
+const uschar * data;
if (rdata->isfile)
{
static int
rda_write_string(int fd, const uschar *s)
{
-int len = (s == NULL)? 0 : Ustrlen(s) + 1;
+int len = s ? Ustrlen(s) + 1 : 0;
return ( write(fd, &len, sizeof(int)) != sizeof(int)
- || (s != NULL && write(fd, s, len) != len)
+ || (s && write(fd, s, len) != len)
)
? -1 : 0;
}
*/
static BOOL
-rda_read_string(int fd, uschar **sp)
+rda_read_string(int fd, uschar ** sp)
{
int len;
/* We know we have enough memory so disable the error on "len" */
/* coverity[tainted_data] */
/* We trust the data source, so untainted */
- if (read(fd, *sp = store_get(len, FALSE), len) != len) return FALSE;
+ if (read(fd, *sp = store_get(len, GET_UNTAINTED), len) != len) return FALSE;
return TRUE;
}
*/
int
-rda_interpret(redirect_block *rdata, int options, uschar *include_directory,
- uschar *sieve_vacation_directory, uschar *sieve_enotify_mailto_owner,
- uschar *sieve_useraddress, uschar *sieve_subaddress, ugid_block *ugid,
- address_item **generated, uschar **error, error_block **eblockp,
- int *filtertype, uschar *rname)
+rda_interpret(redirect_block * rdata, int options,
+ const uschar * include_directory, const uschar * sieve_vacation_directory,
+ const uschar * sieve_enotify_mailto_owner, const uschar * sieve_useraddress,
+ const uschar * sieve_subaddress, const ugid_block * ugid, address_item ** generated,
+ uschar ** error, error_block ** eblockp, int * filtertype, const uschar * rname)
{
int fd, rc, pfd[2];
int yield, status;
uschar *s;
if (!rda_read_string(fd, &s)) goto DISASTER;
if (!s) break;
- e = store_get(sizeof(error_block), FALSE);
+ e = store_get(sizeof(error_block), GET_UNTAINTED);
e->next = NULL;
e->text1 = s;
if (!rda_read_string(fd, &s)) goto DISASTER;
for (;;)
{
int i, reply_options;
- address_item *addr;
- uschar *recipient;
- uschar *expandn[EXPAND_MAXN + 2];
+ address_item * addr;
+ uschar * recipient, * s;
+ uschar * expandn[EXPAND_MAXN + 2];
/* First string is the address; NULL => end of addresses */
if ( read(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode)
|| read(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags)
- || !rda_read_string(fd, &addr->prop.errors_address)
+ || !rda_read_string(fd, &s)
|| read(fd, &i, sizeof(i)) != sizeof(i)
)
goto DISASTER;
+ addr->prop.errors_address = s;
addr->prop.ignore_error = (i != 0);
/* Next comes a possible setting for $thisaddress and any numerical
if (i > 0)
{
- addr->pipe_expandn = store_get((i+1) * sizeof(uschar *), FALSE);
+ addr->pipe_expandn = store_get((i+1) * sizeof(uschar *), GET_UNTAINTED);
addr->pipe_expandn[i] = NULL;
while (--i >= 0) addr->pipe_expandn[i] = expandn[i];
}
if (read(fd, &reply_options, sizeof(int)) != sizeof(int)) goto DISASTER;
if ((reply_options & REPLY_EXISTS) != 0)
{
- addr->reply = store_get(sizeof(reply_item), FALSE);
+ addr->reply = store_get(sizeof(reply_item), GET_UNTAINTED);
addr->reply->file_expand = (reply_options & REPLY_EXPAND) != 0;
addr->reply->return_message = (reply_options & REPLY_RETURN) != 0;
*error = string_sprintf("internal problem in %s: failure to transfer "
"data from subprocess: status=%04x%s%s%s", rname,
status, readerror,
- (*error == NULL)? US"" : US": error=",
- (*error == NULL)? US"" : *error);
+ *error ? US": error=" : US"",
+ *error ? *error : US"");
log_write(0, LOG_MAIN|LOG_PANIC, "%s", *error);
}
else if (status != 0)
- {
log_write(0, LOG_MAIN|LOG_PANIC, "internal problem in %s: unexpected status "
"%04x from redirect subprocess (but data correctly received)", rname,
status);
- }
FINAL_EXIT:
(void)close(fd);