From: Sarah Day Date: Tue, 19 Jan 2016 14:50:33 +0000 (-0500) Subject: Add unit tests for k5_parse_host_string X-Git-Tag: krb5-1.15-beta1~121 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef1e428b19aca8a692d2ca77750a5c38b3787eae;p=thirdparty%2Fkrb5.git Add unit tests for k5_parse_host_string Make is_string_numeric() visible outside of parse_host_string.c as k5_is_string_numeric() so it can be tested. Make k5_parse_host_string() return an error when address begins with ':', for consistency with APR's apr_parse_addr_port(). [ghudson@mit.edu: squashed three commits; added t_parse_host_string to .gitignore and clean rule; clarified commit message] --- diff --git a/.gitignore b/.gitignore index 3b63c98d97..4baf11a340 100644 --- a/.gitignore +++ b/.gitignore @@ -331,6 +331,7 @@ local.properties /src/lib/krb5/krb/t_in_ccache /src/lib/krb5/krb/t_kerb /src/lib/krb5/krb/t_pac +/src/lib/krb5/krb/t_parse_host_string /src/lib/krb5/krb/t_princ /src/lib/krb5/krb/t_ser /src/lib/krb5/krb/t_vfy_increds diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 0ed8b70c82..eb73fa75a0 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1758,6 +1758,10 @@ krb5_encode_kdc_rep(krb5_context, krb5_msgtype, const krb5_enc_kdc_rep_part *, int using_subkey, const krb5_keyblock *, krb5_kdc_rep *, krb5_data ** ); +/* Return true if s is non-empty and composed solely of digits. */ +krb5_boolean +k5_is_string_numeric(const char *s); + krb5_error_code k5_parse_host_string(const char *address, int default_port, char **host_out, int *port_out); diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 7a7ae2ebb8..0fe02a95d0 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -354,6 +354,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/t_deltat.c \ $(srcdir)/t_expand.c \ $(srcdir)/t_pac.c \ + $(srcdir)/t_parse_host_string.c \ $(srcdir)/t_princ.c \ $(srcdir)/t_etypes.c \ $(srcdir)/t_expire_warn.c \ @@ -398,6 +399,8 @@ T_PRINC_OBJS= t_princ.o parse.o unparse.o T_ETYPES_OBJS= t_etypes.o init_ctx.o etype_list.o plugin.o +T_PARSE_HOST_STRING_OBJS= t_parse_host_string.o parse_host_string.o + t_walk_rtree: $(T_WALK_RTREE_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_walk_rtree $(T_WALK_RTREE_OBJS) $(KRB5_BASE_LIBS) t_ad_fx_armor: t_ad_fx_armor.o @@ -410,7 +413,7 @@ t_kerb: $(T_KERB_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_kerb $(T_KERB_OBJS) $(KRB5_BASE_LIBS) t_ser: $(T_SER_OBJS) $(KRB5_BASE_DEPLIBS) - $(CC_LINK) -o t_ser $(T_SER_OBJS) $(KRB5_BASE_LIBS) + $(CC_LINK) -o t_ser $(T_SER_OBJS) $(KRB5_BASE_LIBS) t_deltat : $(T_DELTAT_OBJS) $(SUPPORT_DEPLIB) $(CC_LINK) -o t_deltat $(T_DELTAT_OBJS) $(SUPPORT_LIB) @@ -429,6 +432,10 @@ t_princ: $(T_PRINC_OBJS) $(KRB5_BASE_DEPLIBS) t_etypes: $(T_ETYPES_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_etypes $(T_ETYPES_OBJS) $(KRB5_BASE_LIBS) +t_parse_host_string: $(T_PARSE_HOST_STRING_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_PARSE_HOST_STRING_OBJS) $(CMOCKA_LIBS) \ + $(KRB5_BASE_LIBS) + t_expire_warn: t_expire_warn.o $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o $@ t_expire_warn.o $(KRB5_BASE_LIBS) @@ -495,6 +502,9 @@ check-pytests: t_expire_warn t_vfy_increds $(RUNPYTEST) $(srcdir)/t_vfy_increds.py $(PYTESTFLAGS) $(RUNPYTEST) $(srcdir)/t_in_ccache_patypes.py $(PYTESTFLAGS) +check-cmocka: t_parse_host_string + $(RUN_TEST) ./t_parse_host_string > /dev/null + clean: $(RM) $(OUTPRE)t_walk_rtree$(EXEEXT) $(OUTPRE)t_walk_rtree.$(OBJEXT) \ $(OUTPRE)t_kerb$(EXEEXT) $(OUTPRE)t_kerb.$(OBJEXT) \ @@ -513,7 +523,9 @@ clean: $(OUTPRE)t_vfy_increds$(EXEEXT) $(OUTPRE)t_vfy_increds.$(OBJEXT) \ $(OUTPRE)t_response_items$(EXEEXT) \ $(OUTPRE)t_response_items.$(OBJEXT) $(OUTPRE)t_sname_match$(EXEEXT) \ - $(OUTPRE)t_sname_match.$(OBJEXT) + $(OUTPRE)t_sname_match.$(OBJEXT) \ + $(OUTPRE)t_parse_host_string$(EXEEXT) \ + $(OUTPRE)t_parse_host_string.$(OBJEXT) @libobj_frag@ diff --git a/src/lib/krb5/krb/parse_host_string.c b/src/lib/krb5/krb/parse_host_string.c index 7eaa27a6cb..2330be6a51 100644 --- a/src/lib/krb5/krb/parse_host_string.c +++ b/src/lib/krb5/krb/parse_host_string.c @@ -34,8 +34,8 @@ #include /* Return true if s is composed solely of digits. */ -static krb5_boolean -is_string_numeric(const char *s) +krb5_boolean +k5_is_string_numeric(const char *s) { if (*s == '\0') return FALSE; @@ -80,13 +80,13 @@ k5_parse_host_string(const char *address, int default_port, char **host_out, *host_out = NULL; *port_out = 0; - if (address == NULL || *address == '\0') + if (address == NULL || *address == '\0' || *address == ':') return EINVAL; if (default_port < 0 || default_port > 65535) return EINVAL; /* Find the bounds of the host string and the start of the port string. */ - if (is_string_numeric(address)) { + if (k5_is_string_numeric(address)) { port = address; } else if (*address == '[' && (p = strchr(address, ']')) != NULL) { host = address + 1; diff --git a/src/lib/krb5/krb/t_parse_host_string.c b/src/lib/krb5/krb/t_parse_host_string.c new file mode 100644 index 0000000000..76dd20f817 --- /dev/null +++ b/src/lib/krb5/krb/t_parse_host_string.c @@ -0,0 +1,251 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_parse_host_string.c - k5_parse_host_string() unit tests */ +/* + * Copyright (C) 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "k5-int.h" +#include +#include +#include +#include +#include + +/* Call k5_parse_host_string() and check the result against the expected code, + * hostname, and port. */ +static void +call_k5_parse_host_string(const char *host, int default_port, + krb5_error_code e_code, const char *e_host, + int e_port) +{ + krb5_error_code code; + char *host_out = NULL; + int port_out = -1; + + code = k5_parse_host_string(host, default_port, &host_out, &port_out); + + assert_int_equal(code, e_code); + + /* Only check the port if the function was expected to be successful. */ + if (!e_code) + assert_int_equal(port_out, e_port); + + /* If the expected code is a failure then host_out should be NULL. */ + if (e_code != 0 || e_host == NULL) + assert_null(host_out); + else + assert_string_equal(e_host, host_out); + + free(host_out); +} + +/* k5_parse_host_string() tests */ + +static void +test_named_host_only(void **state) +{ + call_k5_parse_host_string("test.example", 50, 0, "test.example", 50); +} + +static void +test_named_host_w_port(void **state) +{ + call_k5_parse_host_string("test.example:75", 0, 0, "test.example", 75); +} + +static void +test_ipv4_only(void **state) +{ + call_k5_parse_host_string("192.168.1.1", 100, 0, "192.168.1.1", 100); +} + +static void +test_ipv4_w_port(void **state) +{ + call_k5_parse_host_string("192.168.1.1:150", 0, 0, "192.168.1.1", 150); +} + +static void +test_ipv6_only(void **state) +{ + call_k5_parse_host_string("[BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE]", 200, + 0, "BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE", + 200); +} + +static void +test_ipv6_w_port(void **state) +{ + call_k5_parse_host_string("[BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE]:250", + 0, 0, "BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE", + 250); +} + +static void +test_ipv6_w_zone(void **state) +{ + call_k5_parse_host_string("[BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE%eth0]", + 275, 0, + "BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE%eth0", + 275); +} + +static void +test_invalid_ipv6(void **state) +{ + call_k5_parse_host_string("BEEF:CAFE:FEED:FACE:DEAD:BEEF:DEAF:BABE", 1, + EINVAL, NULL, 0); +} + +static void +test_no_host_port(void **state) +{ + call_k5_parse_host_string(":300", 0, EINVAL, NULL, 300); +} + +static void +test_port_only(void **state) +{ + call_k5_parse_host_string("350", 0, 0, NULL, 350); +} + +static void +test_null_host(void **state) +{ + call_k5_parse_host_string(NULL, 400, EINVAL, NULL, 400); +} + +static void +test_empty_host(void **state) +{ + call_k5_parse_host_string("", 450, EINVAL, NULL, 450); +} + +static void +test_port_out_of_range(void **state) +{ + call_k5_parse_host_string("70000", 1, EINVAL, NULL, 0); +} + +static void +test_port_invalid_characters(void **state) +{ + call_k5_parse_host_string("test.example:F101", 1, EINVAL, NULL, 0); +} + +static void +test_invalid_default_port(void **state) +{ + call_k5_parse_host_string("test.example", 70000, EINVAL, NULL, 0); +} + +/* k5_is_string_numeric() tests */ + +static void +test_numeric_single_digit(void **state) +{ + assert_true(k5_is_string_numeric("0")); +} + +static void +test_numeric_all_digits(void **state) +{ + assert_true(k5_is_string_numeric("0123456789")); +} + +static void +test_numeric_alpha(void **state) +{ + assert_false(k5_is_string_numeric("012345F6789")); +} + +static void +test_numeric_period(void **state) +{ + assert_false(k5_is_string_numeric("123.456")); +} + +static void +test_numeric_negative(void **state) +{ + assert_false(k5_is_string_numeric("-123")); +} + +static void +test_numeric_empty(void **state) +{ + assert_false(k5_is_string_numeric("")); +} + +static void +test_numeric_whitespace(void **state) +{ + assert_false(k5_is_string_numeric("123 456")); +} + +int +main(void) +{ + int ret; + + const struct CMUnitTest k5_parse_host_string_tests[] = { + cmocka_unit_test(test_named_host_only), + cmocka_unit_test(test_named_host_w_port), + cmocka_unit_test(test_ipv4_only), + cmocka_unit_test(test_ipv4_w_port), + cmocka_unit_test(test_ipv6_only), + cmocka_unit_test(test_ipv6_w_port), + cmocka_unit_test(test_ipv6_w_zone), + cmocka_unit_test(test_invalid_ipv6), + cmocka_unit_test(test_no_host_port), + cmocka_unit_test(test_port_only), + cmocka_unit_test(test_null_host), + cmocka_unit_test(test_empty_host), + cmocka_unit_test(test_port_out_of_range), + cmocka_unit_test(test_port_invalid_characters), + cmocka_unit_test(test_invalid_default_port) + }; + + const struct CMUnitTest k5_is_string_numeric_tests[] = { + cmocka_unit_test(test_numeric_single_digit), + cmocka_unit_test(test_numeric_all_digits), + cmocka_unit_test(test_numeric_alpha), + cmocka_unit_test(test_numeric_period), + cmocka_unit_test(test_numeric_negative), + cmocka_unit_test(test_numeric_empty), + cmocka_unit_test(test_numeric_whitespace) + }; + + ret = cmocka_run_group_tests_name("k5_parse_host_string", + k5_parse_host_string_tests, NULL, NULL); + ret += cmocka_run_group_tests_name("k5_is_string_numeric", + k5_is_string_numeric_tests, NULL, NULL); + + return ret; +} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index e350c89f99..cdda32df28 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -131,6 +131,7 @@ k5_free_secure_cookie k5_free_serverlist k5_hostrealm_free_context k5_init_trace +k5_is_string_numeric k5_kt_get_principal k5_localauth_free_context k5_locate_kdc