diff options
author | Francis Dupont <fdupont@isc.org> | 2019-10-29 13:45:42 +0100 |
---|---|---|
committer | Francis Dupont <fdupont@isc.org> | 2019-11-09 19:28:09 +0100 |
commit | eb9885003bfa0058ce21b512199c2f9623464723 (patch) | |
tree | 5e350ecea8e5446181b9ddb30182b1357c4c690b | |
parent | f17190e1b32daa6dddfa6f6584ccaac3c70330c5 (diff) | |
download | isc-dhcp-eb9885003bfa0058ce21b512199c2f9623464723.tar.gz |
Fixed output
-rw-r--r-- | common/ns_name.c | 35 | ||||
-rw-r--r-- | common/options.c | 85 | ||||
-rw-r--r-- | common/tests/Kyuafile | 1 | ||||
-rw-r--r-- | common/tests/Makefile.am | 11 | ||||
-rw-r--r-- | common/tests/Makefile.in | 9 | ||||
-rw-r--r-- | common/tests/domain_name_test.c | 100 | ||||
-rw-r--r-- | includes/ns_name.h | 3 |
7 files changed, 238 insertions, 6 deletions
diff --git a/common/ns_name.c b/common/ns_name.c index be035f6f..f5198219 100644 --- a/common/ns_name.c +++ b/common/ns_name.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-2003 by Internet Software Consortium * * This Source Code Form is subject to the terms of the Mozilla Public @@ -48,6 +48,39 @@ static int dn_find(const u_char *, const u_char *, /* Public. */ /* + * MRns_name_len(eom, src) + * Compute the length of encoded uncompressed domain name. + * return: + * -1 if it fails, or to be consumed octets if it succeeds. + */ +int +MRns_name_len(const u_char *eom, const u_char *src) +{ + const u_char *srcp; + unsigned n; + int len; + + len = -1; + srcp = src; + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Limit checks. */ + if (srcp + n >= eom) { + errno = EMSGSIZE; + return (-1); + } + srcp += n; + } + if (len < 0) + len = srcp - src; + return (len); +} + +/* * MRns_name_ntop(src, dst, dstsiz) * Convert an encoded domain name to printable ascii as per RFC1035. * return: diff --git a/common/options.c b/common/options.c index eb05ec9e..405f7049 100644 --- a/common/options.c +++ b/common/options.c @@ -35,6 +35,8 @@ struct option *vendor_cfg_option; static int pretty_text(char **, char *, const unsigned char **, const unsigned char *, int); +static int pretty_dname(char **, char *, const unsigned char *, + const unsigned char *); static int pretty_domain(char **, char *, const unsigned char **, const unsigned char *); static int prepare_option_buffer(struct universe *universe, struct buffer *bp, @@ -1628,7 +1630,6 @@ format_has_text(format) p = format; while (*p != '\0') { switch (*p++) { - case 'd': case 't': return 1; @@ -1642,6 +1643,7 @@ format_has_text(format) case 'X': case 'x': case 'D': + case 'd': return 0; case 'c': @@ -1884,8 +1886,23 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) numhunk = -2; break; case 'd': - fmtbuf[l] = 't'; - /* Fall Through ! */ + /* Should not be optional, array or compressed */ + if ((option->format[i+1] == 'o') || + (option->format[i+1] == 'a') || + (option->format[i+1] == 'A') || + (option->format[i+1] == 'c')) { + log_error("%s: Illegal use of domain name: %s", + option->name, + &(option->format[i-1])); + fmtbuf[l + 1] = 0; + } + k = MRns_name_len(data + len, data + hunksize); + if (k == -1) { + log_error("Invalid domain name."); + return "<error>"; + } + hunksize += k; + break; case 't': fmtbuf[l + 1] = 0; numhunk = -2; @@ -2039,6 +2056,18 @@ const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) } *op = 0; break; + case 'd': /* RFC1035 format name */ + k = MRns_name_len(data + len, dp); + /* Already tested... */ + if (k == -1) { + log_error("invalid domain name."); + return "<error>"; + } + pretty_dname(&op, endbuf-1, dp, data + len); + /* pretty_dname does not add the nul */ + *op = '\0'; + dp += k; + break; case 'D': /* RFC1035 format name list */ for( ; dp < (data + len) ; dp += k) { unsigned char nbuff[NS_MAXCDNAME]; @@ -4286,6 +4315,56 @@ pretty_text(char **dst, char *dend, const unsigned char **src, } static int +pretty_dname(char **dst, char *dend, const unsigned char *src, + const unsigned char *send) +{ + const unsigned char *tend; + const unsigned char *srcp = src; + int count = 0; + int tsiz, status; + + if (dst == NULL || dend == NULL || src == NULL || send == NULL || + *dst == NULL || ((*dst + 1) > dend) || (src >= send)) + return -1; + + do { + /* Continue loop until end of src buffer. */ + if (srcp >= send) + break; + + /* Consume tag size. */ + tsiz = *srcp; + srcp++; + + /* At root, finis. */ + if (tsiz == 0) + break; + + tend = srcp + tsiz; + + /* If the tag exceeds the source buffer, it's illegal. + * This should also trap compression pointers (which should + * not be in these buffers). + */ + if (tend > send) + return -1; + + /* dend-1 leaves room for a trailing dot and quote. */ + status = pretty_escape(dst, dend-1, &srcp, tend); + + if ((status == -1) || ((*dst + 1) > dend)) + return -1; + + **dst = '.'; + (*dst)++; + count += status + 1; + } + while(1); + + return count; +} + +static int pretty_domain(char **dst, char *dend, const unsigned char **src, const unsigned char *send) { diff --git a/common/tests/Kyuafile b/common/tests/Kyuafile index f3c352db..4952b549 100644 --- a/common/tests/Kyuafile +++ b/common/tests/Kyuafile @@ -3,6 +3,7 @@ test_suite('isc-dhcp') atf_test_program{name='alloc_unittest'} atf_test_program{name='dns_unittest'} +atf_test_program{name='domain_name_unittest'} atf_test_program{name='misc_unittest'} atf_test_program{name='ns_name_unittest'} atf_test_program{name='option_unittest'} diff --git a/common/tests/Makefile.am b/common/tests/Makefile.am index 322f77e8..a5152653 100644 --- a/common/tests/Makefile.am +++ b/common/tests/Makefile.am @@ -9,7 +9,7 @@ ATF_TESTS = if HAVE_ATF ATF_TESTS += alloc_unittest dns_unittest misc_unittest ns_name_unittest \ - option_unittest + option_unittest domain_name_unittest alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c alloc_unittest_LDADD = $(ATF_LDFLAGS) @@ -51,6 +51,15 @@ option_unittest_LDADD += ../libdhcp.@A@ ../../omapip/libomapi.@A@ \ @BINDLIBISCCFGDIR@/libisccfg.@A@ \ @BINDLIBISCDIR@/libisc.@A@ +domain_name_unittest_SOURCES = domain_name_test.c \ + $(top_srcdir)/tests/t_api_dhcp.c +domain_name_unittest_LDADD = $(ATF_LDFLAGS) +domain_name_unittest_LDADD += ../libdhcp.@A@ ../../omapip/libomapi.@A@ \ + @BINDLIBIRSDIR@/libirs.@A@ \ + @BINDLIBDNSDIR@/libdns.@A@ \ + @BINDLIBISCCFGDIR@/libisccfg.@A@ \ + @BINDLIBISCDIR@/libisc.@A@ + check: $(ATF_TESTS) @if test $(top_srcdir) != ${top_builddir}; then \ cp $(top_srcdir)/common/tests/Atffile Atffile; \ diff --git a/common/tests/Makefile.in b/common/tests/Makefile.in index 0fb4d408..b4ecc15c 100644 --- a/common/tests/Makefile.in +++ b/common/tests/Makefile.in @@ -416,6 +416,15 @@ ATF_TESTS = $(am__append_1) @HAVE_ATF_TRUE@ @BINDLIBDNSDIR@/libdns.@A@ \ @HAVE_ATF_TRUE@ @BINDLIBISCCFGDIR@/libisccfg.@A@ \ @HAVE_ATF_TRUE@ @BINDLIBISCDIR@/libisc.@A@ +@HAVE_ATF_TRUE@domain_name_unittest_SOURCES = domain_name_test.c \ +@HAVE_ATF_TRUE@ $(top_srcdir)/tests/t_api_dhcp.c + +@HAVE_ATF_TRUE@domain_name_unittest_LDADD = $(ATF_LDFLAGS) \ +@HAVE_ATF_TRUE@ ../libdhcp.@A@ ../../omapip/libomapi.@A@ \ +@HAVE_ATF_TRUE@ @BINDLIBIRSDIR@/libirs.@A@ \ +@HAVE_ATF_TRUE@ @BINDLIBDNSDIR@/libdns.@A@ \ +@HAVE_ATF_TRUE@ @BINDLIBISCCFGDIR@/libisccfg.@A@ \ +@HAVE_ATF_TRUE@ @BINDLIBISCDIR@/libisc.@A@ all: all-recursive .SUFFIXES: diff --git a/common/tests/domain_name_test.c b/common/tests/domain_name_test.c new file mode 100644 index 00000000..8bd70aa2 --- /dev/null +++ b/common/tests/domain_name_test.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2019 Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> +#include <atf-c.h> +#include "dhcpd.h" + +ATF_TC(pretty_print_domain_name); + +ATF_TC_HEAD(pretty_print_domain_name, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify pretty_print_option can render a domain name."); +} + +/* + * This test verifies that pretty_print_option() correctly render a + * domain name. + * + */ +ATF_TC_BODY(pretty_print_domain_name, tc) +{ + struct option *option; + unsigned code; + unsigned char good_data[] = + { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00 }; + unsigned char short_data[] = + { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d }; + unsigned char long_data[] = + { 0x05, 0x62, 0x6f, 0x6f, 0x79, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, + 0x01, 0x02 }; + const char *output_buf; + + initialize_common_option_spaces(); + + /* We'll use v4-lost because it happens to be format d */ + code = 137; + option = NULL; + if (!option_code_hash_lookup(&option, dhcp_universe.code_hash, + &code, 0, MDL)) { + atf_tc_fail("can't find option %d", code); + } + + if (option == NULL) { + atf_tc_fail("option is NULL"); + } + + /* First we will try a good value we know should fit. */ + output_buf = pretty_print_option(option, good_data, sizeof(good_data), 0, + 0); + + /* Make sure we get what we expect */ + if (!output_buf || strcmp(output_buf, "booya.com.")) { + atf_tc_fail("pretty_print_option did not return 'booya.com.'"); + } + + fprintf(stderr, "good!\n"); + + /* Now we'll try a data value that's too short */ + output_buf = pretty_print_option(option, short_data, sizeof(short_data), + 0, 0); + + /* Make sure we safely get an error */ + if (!output_buf || strcmp(output_buf, "<error>")) { + atf_tc_fail("pretty_print_option did not return \"<error>\""); + } + + /* Now we'll try a data value that's too large */ + output_buf = pretty_print_option(option, long_data, sizeof(long_data), 0, + 0); + + /* This logs but does not return an error */ + if (!output_buf || strcmp(output_buf, "booya.com.")) { + atf_tc_fail("pretty_print_option did not return 'booya.com.' (large)"); + } +} + + +/* This macro defines main() method that will call specified + test cases. tp and simple_test_case names can be whatever you want + as long as it is a valid variable identifier. */ +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pretty_print_domain_name); + + return (atf_no_error()); +} diff --git a/includes/ns_name.h b/includes/ns_name.h index 5095c1ce..a2c42769 100644 --- a/includes/ns_name.h +++ b/includes/ns_name.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2001-2003 by Internet Software Consortium * * This Source Code Form is subject to the terms of the Mozilla Public @@ -31,6 +31,7 @@ * <viraj_bais@ccm.fm.intel.com> */ +int MRns_name_len(const unsigned char *, const unsigned char *); int MRns_name_compress(const char *, u_char *, size_t, const unsigned char **, const unsigned char **); int MRns_name_unpack(const unsigned char *, const unsigned char *, |