mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-31 14:25:41 +00:00
Do careful bounds checking on the incoming fqdn option.
This commit is contained in:
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: options.c,v 1.79 2001/01/16 23:00:49 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
|
"$Id: options.c,v 1.80 2001/01/19 10:56:06 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#define DHCP_OPTION_DATA
|
#define DHCP_OPTION_DATA
|
||||||
@@ -269,7 +269,7 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
struct buffer *bp = (struct buffer *)0;
|
struct buffer *bp = (struct buffer *)0;
|
||||||
|
|
||||||
/* FQDN options have to be at least four bytes long. */
|
/* FQDN options have to be at least four bytes long. */
|
||||||
if (length < 4)
|
if (length < 3)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Save the contents of the option in a buffer. */
|
/* Save the contents of the option in a buffer. */
|
||||||
@@ -291,32 +291,14 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer [0] & 2) /* no-client-update */
|
|
||||||
bp -> data [1] = 1;
|
|
||||||
else
|
|
||||||
bp -> data [1] = 0;
|
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
|
||||||
&bp -> data [1], 1,
|
|
||||||
&fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
if (buffer [0] & 1) /* server-update */
|
if (buffer [0] & 1) /* server-update */
|
||||||
bp -> data [2] = 1;
|
bp -> data [2] = 1;
|
||||||
else
|
else
|
||||||
bp -> data [2] = 0;
|
bp -> data [2] = 0;
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
if (buffer [0] & 2) /* no-client-update */
|
||||||
&bp -> data [2], 1,
|
bp -> data [1] = 1;
|
||||||
&fqdn_options [FQDN_SERVER_UPDATE], 0))
|
else
|
||||||
goto bad;
|
bp -> data [1] = 0;
|
||||||
|
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
|
||||||
&bp -> data [3], 1,
|
|
||||||
&fqdn_options [FQDN_RCODE1], 0))
|
|
||||||
goto bad;
|
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
|
||||||
&bp -> data [4], 1,
|
|
||||||
&fqdn_options [FQDN_RCODE2], 0))
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
/* XXX Ideally we should store the name in DNS format, so if the
|
/* XXX Ideally we should store the name in DNS format, so if the
|
||||||
XXX label isn't in DNS format, we convert it to DNS format,
|
XXX label isn't in DNS format, we convert it to DNS format,
|
||||||
@@ -328,6 +310,12 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
if (!bp -> data [0]) {
|
if (!bp -> data [0]) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
/* Some broken clients NUL-terminate this option. */
|
||||||
|
if (buffer [length - 1] == 0) {
|
||||||
|
--length;
|
||||||
|
bp -> data [1] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine the length of the hostname component of the
|
/* Determine the length of the hostname component of the
|
||||||
name. If the name contains no '.' character, it
|
name. If the name contains no '.' character, it
|
||||||
represents a non-qualified label. */
|
represents a non-qualified label. */
|
||||||
@@ -336,9 +324,11 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
|
|
||||||
/* Note: If the client sends a FQDN, the first '.' will
|
/* Note: If the client sends a FQDN, the first '.' will
|
||||||
be used as a NUL terminator for the hostname. */
|
be used as a NUL terminator for the hostname. */
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
if (i)
|
||||||
&bp -> data[5], i,
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
&fqdn_options [FQDN_HOSTNAME], 0))
|
&bp -> data[5], i,
|
||||||
|
&fqdn_options [FQDN_HOSTNAME],
|
||||||
|
0))
|
||||||
goto bad;
|
goto bad;
|
||||||
/* Note: If the client sends a single label, the
|
/* Note: If the client sends a single label, the
|
||||||
FQDN_DOMAINNAME option won't be set. */
|
FQDN_DOMAINNAME option won't be set. */
|
||||||
@@ -348,10 +338,11 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
&fqdn_options [FQDN_DOMAINNAME], 1))
|
&fqdn_options [FQDN_DOMAINNAME], 1))
|
||||||
goto bad;
|
goto bad;
|
||||||
/* Also save the whole name. */
|
/* Also save the whole name. */
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
if (length > 3)
|
||||||
&bp -> data [5], length - 3,
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
&fqdn_options [FQDN_FQDN], 1))
|
&bp -> data [5], length - 3,
|
||||||
goto bad;
|
&fqdn_options [FQDN_FQDN], 1))
|
||||||
|
goto bad;
|
||||||
} else {
|
} else {
|
||||||
unsigned len;
|
unsigned len;
|
||||||
unsigned total_len = 0;
|
unsigned total_len = 0;
|
||||||
@@ -361,7 +352,7 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
|
|
||||||
s = &bp -> data[5];
|
s = &bp -> data[5];
|
||||||
|
|
||||||
do {
|
while (s < &bp -> data[0] + length + 2) {
|
||||||
len = *s;
|
len = *s;
|
||||||
if (len > 63) {
|
if (len > 63) {
|
||||||
log_info ("fancy bits in fqdn option");
|
log_info ("fancy bits in fqdn option");
|
||||||
@@ -383,29 +374,49 @@ int fqdn_universe_decode (struct option_state *options,
|
|||||||
*s = '.';
|
*s = '.';
|
||||||
s += len + 1;
|
s += len + 1;
|
||||||
total_len += len;
|
total_len += len;
|
||||||
} while (s < &bp -> data[0] + length + 3);
|
}
|
||||||
|
|
||||||
if (!terminated) {
|
if (!terminated) {
|
||||||
first_len = total_len;
|
first_len = total_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
if (first_len > 0 &&
|
||||||
|
!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
&bp -> data[6], first_len,
|
&bp -> data[6], first_len,
|
||||||
&fqdn_options [FQDN_HOSTNAME], 0))
|
&fqdn_options [FQDN_HOSTNAME], 0))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (first_len != total_len) {
|
if (total_len > 0 && first_len != total_len) {
|
||||||
if (!save_option_buffer
|
if (!save_option_buffer
|
||||||
(&fqdn_universe, options, bp,
|
(&fqdn_universe, options, bp,
|
||||||
&bp -> data[6 + first_len],
|
&bp -> data[6 + first_len], total_len - first_len,
|
||||||
total_len - first_len,
|
|
||||||
&fqdn_options [FQDN_DOMAINNAME], 1))
|
&fqdn_options [FQDN_DOMAINNAME], 1))
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (!save_option_buffer (&fqdn_universe, options, bp,
|
if (total_len > 0)
|
||||||
&bp -> data [6], total_len,
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
&fqdn_options [FQDN_FQDN], 1))
|
&bp -> data [6], total_len,
|
||||||
goto bad;
|
&fqdn_options [FQDN_FQDN], 1))
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
|
&bp -> data [1], 1,
|
||||||
|
&fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
|
||||||
|
goto bad;
|
||||||
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
|
&bp -> data [2], 1,
|
||||||
|
&fqdn_options [FQDN_SERVER_UPDATE], 0))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
|
&bp -> data [3], 1,
|
||||||
|
&fqdn_options [FQDN_RCODE1], 0))
|
||||||
|
goto bad;
|
||||||
|
if (!save_option_buffer (&fqdn_universe, options, bp,
|
||||||
|
&bp -> data [4], 1,
|
||||||
|
&fqdn_options [FQDN_RCODE2], 0))
|
||||||
|
goto bad;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user