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
DNS: more hardening against crafted responses
[exim.git]
/
src
/
src
/
host.c
diff --git
a/src/src/host.c
b/src/src/host.c
index b6c2ea0827053c3e8a2daedbd249200e042d94d0..ce7ca2bab1098d6f5167cd485dd46c42d0451163 100644
(file)
--- a/
src/src/host.c
+++ b/
src/src/host.c
@@
-5,6
+5,7
@@
/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
/* Copyright (c) The Exim Maintainers 2020 - 2022 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
directly via the DNS. When IPv6 is supported, getipnodebyname() and
/* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or
directly via the DNS. When IPv6 is supported, getipnodebyname() and
@@
-599,35
+600,38
@@
return depends on whether sender_fullhost and sender_ident are set or not:
ident set, no host => U=ident
ident set, host set => H=sender_fullhost U=ident
ident set, no host => U=ident
ident set, host set => H=sender_fullhost U=ident
-Use taint-unchecked routines on the assumption we'll never expand the results.
-
Arguments:
useflag TRUE if first item to be flagged (H= or U=); if there are two
items, the second is always flagged
Arguments:
useflag TRUE if first item to be flagged (H= or U=); if there are two
items, the second is always flagged
-Returns: pointer to a
string in big_buffer
+Returns: pointer to a
n allocated string
*/
uschar *
host_and_ident(BOOL useflag)
{
*/
uschar *
host_and_ident(BOOL useflag)
{
+gstring * g = NULL;
+
if (!sender_fullhost)
if (!sender_fullhost)
- string_format_nt(big_buffer, big_buffer_size, "%s%s", useflag ? "U=" : "",
- sender_ident ? sender_ident : US"unknown");
+ {
+ if (useflag)
+ g = string_catn(g, US"U=", 2);
+ g = string_cat(g, sender_ident ? sender_ident : US"unknown");
+ }
else
{
else
{
- uschar * flag = useflag ? US"H=" : US"";
- uschar * iface = US"";
+ if (useflag)
+ g = string_catn(g, US"H=", 2);
+ g = string_cat(g, sender_fullhost);
if (LOGGING(incoming_interface) && interface_address)
if (LOGGING(incoming_interface) && interface_address)
-
iface = string_sprintf(
" I=[%s]:%d", interface_address, interface_port);
+
g = string_fmt_append(g,
" I=[%s]:%d", interface_address, interface_port);
if (sender_ident)
if (sender_ident)
- string_format_nt(big_buffer, big_buffer_size, "%s%s%s U=%s",
- flag, sender_fullhost, iface, sender_ident);
- else
- string_format_nt(big_buffer, big_buffer_size, "%s%s%s",
- flag, sender_fullhost, iface);
+ g = string_fmt_append(g, " U=%s", sender_ident);
}
}
-return big_buffer;
+if (LOGGING(connection_id))
+ g = string_fmt_append(g, " Ci=%lu", connection_id);
+gstring_release_unused(g);
+return string_from_gstring(g);
}
#endif /* STAND_ALONE */
}
#endif /* STAND_ALONE */
@@
-823,9
+827,9
@@
Returns: pointer to character string
*/
uschar *
*/
uschar *
-host_ntoa(int type, const void *
arg, uschar *buffer, int *
portptr)
+host_ntoa(int type, const void *
arg, uschar * buffer, int *
portptr)
{
{
-uschar *yield;
+uschar *
yield;
/* The new world. It is annoying that we have to fish out the address from
different places in the block, depending on what kind of address it is. It
/* The new world. It is annoying that we have to fish out the address from
different places in the block, depending on what kind of address it is. It
@@
-911,7
+915,7
@@
Returns: the number of ints used
*/
int
*/
int
-host_aton(const uschar *
address, int *
bin)
+host_aton(const uschar *
address, int *
bin)
{
int x[4];
int v4offset = 0;
{
int x[4];
int v4offset = 0;
@@
-923,13
+927,10
@@
supported. */
if (Ustrchr(address, ':') != NULL)
{
if (Ustrchr(address, ':') != NULL)
{
- const uschar *p = address;
- const uschar *component[8];
+ const uschar *
p = address;
+ const uschar *
component[8];
BOOL ipv4_ends = FALSE;
BOOL ipv4_ends = FALSE;
- int ci = 0;
- int nulloffset = 0;
- int v6count = 8;
- int i;
+ int ci = 0, nulloffset = 0, v6count = 8, i;
/* If the address starts with a colon, it will start with two colons.
Just lose the first one, which will leave a null first component. */
/* If the address starts with a colon, it will start with two colons.
Just lose the first one, which will leave a null first component. */
@@
-941,7
+942,7
@@
if (Ustrchr(address, ':') != NULL)
overlooked; to guard against that happening again, check here and crash if
there are too many components. */
overlooked; to guard against that happening again, check here and crash if
there are too many components. */
- while (*p
!= 0
&& *p != '%')
+ while (*p && *p != '%')
{
int len = Ustrcspn(p, ":%");
if (len == 0) nulloffset = ci;
{
int len = Ustrcspn(p, ":%");
if (len == 0) nulloffset = ci;
@@
-2080,11
+2081,11
@@
so we pass that back. */
if (!host->address)
{
uschar *msg =
if (!host->address)
{
uschar *msg =
-
#ifndef STAND_ALONE
+#ifndef STAND_ALONE
!message_id[0] && smtp_in
? string_sprintf("no IP address found for host %s (during %s)", host->name,
smtp_get_connection_info()) :
!message_id[0] && smtp_in
? string_sprintf("no IP address found for host %s (during %s)", host->name,
smtp_get_connection_info()) :
-
#endif
+#endif
string_sprintf("no IP address found for host %s", host->name);
HDEBUG(D_host_lookup) debug_printf("%s\n", msg);
string_sprintf("no IP address found for host %s", host->name);
HDEBUG(D_host_lookup) debug_printf("%s\n", msg);
@@
-2724,6
+2725,7
@@
for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
const uschar * s = rr->data; /* MUST be unsigned for GETSHORT */
uschar data[256];
const uschar * s = rr->data; /* MUST be unsigned for GETSHORT */
uschar data[256];
+ if (rr_bad_size(rr, sizeof(uint16_t))) continue;
GETSHORT(precedence, s); /* Pointer s is advanced */
/* For MX records, we use a random "weight" which causes multiple records of
GETSHORT(precedence, s); /* Pointer s is advanced */
/* For MX records, we use a random "weight" which causes multiple records of
@@
-2736,6
+2738,8
@@
for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
/* SRV records are specified with a port and a weight. The weight is used
in a special algorithm. However, to start with, we just use it to order the
records of equal priority (precedence). */
/* SRV records are specified with a port and a weight. The weight is used
in a special algorithm. However, to start with, we just use it to order the
records of equal priority (precedence). */
+
+ if (rr_bad_increment(rr, s, 2 * sizeof(uint16_t))) continue;
GETSHORT(weight, s);
GETSHORT(port, s);
}
GETSHORT(weight, s);
GETSHORT(port, s);
}