git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
redirect router: taint-enforce filenames
[exim.git]
/
src
/
src
/
parse.c
diff --git
a/src/src/parse.c
b/src/src/parse.c
index 74817454e5252c13765a6b87dd1077f892ceba10..be70effe9fbda10bc21ed00c72c810971fec65a6 100644
(file)
--- a/
src/src/parse.c
+++ b/
src/src/parse.c
@@
-2,7
+2,7
@@
* Exim - an Internet mail transport agent *
*************************************************/
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 201
7
*/
+/* Copyright (c) University of Cambridge 1995 - 201
8
*/
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for parsing addresses */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for parsing addresses */
@@
-23,7
+23,7
@@
redundant apparatus. */
address_item *deliver_make_addr(uschar *address, BOOL copy)
{
address_item *deliver_make_addr(uschar *address, BOOL copy)
{
-address_item *addr = store_get(sizeof(address_item));
+address_item *addr = store_get(sizeof(address_item)
, FALSE
);
addr->next = NULL;
addr->parent = NULL;
addr->address = address;
addr->next = NULL;
addr->parent = NULL;
addr->address = address;
@@
-618,7
+618,7
@@
uschar *
parse_extract_address(uschar *mailbox, uschar **errorptr, int *start, int *end,
int *domain, BOOL allow_null)
{
parse_extract_address(uschar *mailbox, uschar **errorptr, int *start, int *end,
int *domain, BOOL allow_null)
{
-uschar *yield = store_get(Ustrlen(mailbox) + 1);
+uschar *yield = store_get(Ustrlen(mailbox) + 1
, is_tainted(mailbox)
);
uschar *startptr, *endptr;
uschar *s = US mailbox;
uschar *t = US yield;
uschar *startptr, *endptr;
uschar *s = US mailbox;
uschar *t = US yield;
@@
-658,7
+658,7
@@
if (*s != '@' && *s != '<')
end of string will produce a null local_part and therefore fail. We don't
need to keep updating t, as the phrase isn't to be kept. */
end of string will produce a null local_part and therefore fail. We don't
need to keep updating t, as the phrase isn't to be kept. */
- while (*s != '<' && (!parse_allow_group || *s != ':'))
+ while (*s != '<' && (!
f.
parse_allow_group || *s != ':'))
{
s = read_local_part(s, t, errorptr, FALSE);
if (*errorptr)
{
s = read_local_part(s, t, errorptr, FALSE);
if (*errorptr)
@@
-670,8
+670,8
@@
if (*s != '@' && *s != '<')
if (*s == ':')
{
if (*s == ':')
{
- parse_found_group = TRUE;
- parse_allow_group = FALSE;
+
f.
parse_found_group = TRUE;
+
f.
parse_allow_group = FALSE;
s++;
goto RESTART;
}
s++;
goto RESTART;
}
@@
-790,10
+790,10
@@
move it back past white space if necessary. */
PARSE_SUCCEEDED:
if (*s != 0)
{
PARSE_SUCCEEDED:
if (*s != 0)
{
- if (parse_found_group && *s == ';')
+ if (
f.
parse_found_group && *s == ';')
{
{
- parse_found_group = FALSE;
- parse_allow_group = TRUE;
+
f.
parse_found_group = FALSE;
+
f.
parse_allow_group = TRUE;
}
else
{
}
else
{
@@
-824,10
+824,10
@@
We might have an empty address in a group - the caller can choose to ignore
this. We must, however, keep the flags correct. */
PARSE_FAILED:
this. We must, however, keep the flags correct. */
PARSE_FAILED:
-if (parse_found_group && *s == ';')
+if (
f.
parse_found_group && *s == ';')
{
{
- parse_found_group = FALSE;
- parse_allow_group = TRUE;
+
f.
parse_found_group = FALSE;
+
f.
parse_allow_group = TRUE;
}
return NULL;
}
}
return NULL;
}
@@
-876,7
+876,7
@@
int hlen;
BOOL coded = FALSE;
BOOL first_byte = FALSE;
BOOL coded = FALSE;
BOOL first_byte = FALSE;
-if (
charset == NULL
) charset = US"iso-8859-1";
+if (
!charset
) charset = US"iso-8859-1";
/* We don't expect this to fail! */
/* We don't expect this to fail! */
@@
-925,7
+925,7
@@
for (; len > 0; len--)
*t++ = '=';
*t = 0;
*t++ = '=';
*t = 0;
-return coded? buffer : string;
+return coded
? buffer : string;
}
}
@@
-1277,10
+1277,10
@@
for (;;)
However, if the list is empty only because syntax errors were skipped, we
return FF_DELIVERED. */
However, if the list is empty only because syntax errors were skipped, we
return FF_DELIVERED. */
- if (
*s == 0
)
+ if (
!*s
)
{
{
- return (count > 0 || (syntax_errors
!= NULL && *syntax_errors != NULL))?
- FF_DELIVERED : FF_NOTDELIVERED;
+ return (count > 0 || (syntax_errors
&& *syntax_errors))
+
?
FF_DELIVERED : FF_NOTDELIVERED;
/* This previous code returns FF_ERROR if nothing is generated but a
syntax error has been skipped. I now think it is the wrong approach, but
/* This previous code returns FF_ERROR if nothing is generated but a
syntax error has been skipped. I now think it is the wrong approach, but
@@
-1396,7
+1396,7
@@
for (;;)
if (flen <= 0)
{
if (flen <= 0)
{
- *error =
string_sprintf("file name missing after :include:")
;
+ *error =
US"file name missing after :include:"
;
return FF_ERROR;
}
return FF_ERROR;
}
@@
-1411,7
+1411,7
@@
for (;;)
/* Insist on absolute path */
/* Insist on absolute path */
- if (filename[0]!= '/')
+ if (filename[0]
!= '/')
{
*error = string_sprintf("included file \"%s\" is not an absolute path",
filename);
{
*error = string_sprintf("included file \"%s\" is not an absolute path",
filename);
@@
-1420,12
+1420,19
@@
for (;;)
/* Check if include is permitted */
/* Check if include is permitted */
- if (
(options & RDO_INCLUDE) != 0
)
+ if (
options & RDO_INCLUDE
)
{
*error = US"included files not permitted";
return FF_ERROR;
}
{
*error = US"included files not permitted";
return FF_ERROR;
}
+ if (is_tainted(filename))
+ {
+ *error = string_sprintf("Tainted name '%s' for included file not permitted\n",
+ filename);
+ return FF_ERROR;
+ }
+
/* Check file name if required */
if (directory)
/* Check file name if required */
if (directory)
@@
-1547,7
+1554,7
@@
for (;;)
return FF_ERROR;
}
return FF_ERROR;
}
- filebuf = store_get(statbuf.st_size + 1);
+ filebuf = store_get(statbuf.st_size + 1
, is_tainted(filename)
);
if (fread(filebuf, 1, statbuf.st_size, f) != statbuf.st_size)
{
*error = string_sprintf("error while reading included file %s: %s",
if (fread(filebuf, 1, statbuf.st_size, f) != statbuf.st_size)
{
*error = string_sprintf("error while reading included file %s: %s",
@@
-1623,7
+1630,7
@@
for (;;)
if ((*s == '|' || *s == '/') && (recipient == NULL || domain == 0))
{
if ((*s == '|' || *s == '/') && (recipient == NULL || domain == 0))
{
- uschar *t = store_get(Ustrlen(s) + 1);
+ uschar *t = store_get(Ustrlen(s) + 1
, is_tainted(s)
);
uschar *p = t;
uschar *q = s;
while (*q != 0)
uschar *p = t;
uschar *q = s;
while (*q != 0)
@@
-1662,7
+1669,7
@@
for (;;)
if (syntax_errors != NULL)
{
if (syntax_errors != NULL)
{
- error_block *e = store_get(sizeof(error_block));
+ error_block *e = store_get(sizeof(error_block)
, FALSE
);
error_block *last = *syntax_errors;
if (last == NULL) *syntax_errors = e; else
{
error_block *last = *syntax_errors;
if (last == NULL) *syntax_errors = e; else
{
@@
-1730,6
+1737,7
@@
parse_message_id(uschar *str, uschar **yield, uschar **error)
{
uschar *domain = NULL;
uschar *id;
{
uschar *domain = NULL;
uschar *id;
+rmark reset_point;
str = skip_comment(str);
if (*str != '<')
str = skip_comment(str);
if (*str != '<')
@@
-1742,27
+1750,28
@@
if (*str != '<')
for the answer, but it may also be very long if we are processing a header
line. Therefore, take care to release unwanted store afterwards. */
for the answer, but it may also be very long if we are processing a header
line. Therefore, take care to release unwanted store afterwards. */
-id = *yield = store_get(Ustrlen(str) + 1);
+reset_point = store_mark();
+id = *yield = store_get(Ustrlen(str) + 1, is_tainted(str));
*id++ = *str++;
str = read_addr_spec(str, id, '>', error, &domain);
*id++ = *str++;
str = read_addr_spec(str, id, '>', error, &domain);
-if (
*error == NULL
)
+if (
!*error
)
{
if (*str != '>') *error = US"Missing '>' after message-id";
else if (domain == NULL) *error = US"domain missing in message-id";
}
{
if (*str != '>') *error = US"Missing '>' after message-id";
else if (domain == NULL) *error = US"domain missing in message-id";
}
-if (*error
!= NULL
)
+if (*error)
{
{
- store_reset(
*yield
);
+ store_reset(
reset_point
);
return NULL;
}
return NULL;
}
-while (*id
!= 0
) id++;
+while (*id) id++;
*id++ = *str++;
*id++ = 0;
*id++ = *str++;
*id++ = 0;
-store_re
set
(id);
+store_re
lease_above
(id);
str = skip_comment(str);
return str;
str = skip_comment(str);
return str;
@@
-2149,7
+2158,7
@@
allow_utf8_domains = FALSE;
printf("Testing parse_extract_address with group syntax\n");
printf("Testing parse_extract_address with group syntax\n");
-parse_allow_group = TRUE;
+
f.
parse_allow_group = TRUE;
while (Ufgets(buffer, sizeof(buffer), stdin) != NULL)
{
uschar *out;
while (Ufgets(buffer, sizeof(buffer), stdin) != NULL)
{
uschar *out;