diff --git a/libreswan-4.4-ipcheck.patch b/libreswan-4.4-ipcheck.patch new file mode 100644 index 0000000..fb4ac81 --- /dev/null +++ b/libreswan-4.4-ipcheck.patch @@ -0,0 +1,494 @@ +diff --git a/testing/programs/ipcheck/Makefile b/testing/programs/ipcheck/Makefile +index 4dae8336be..af77a9e9d8 100644 +--- a/testing/programs/ipcheck/Makefile ++++ b/testing/programs/ipcheck/Makefile +@@ -41,4 +41,4 @@ include ../../../mk/program.mk + endif + + local-check: $(PROGRAM) +- $(builddir)/$(PROGRAM) ++ $(builddir)/$(PROGRAM) --dns=yes +diff --git a/testing/programs/ipcheck/ip_address_check.c b/testing/programs/ipcheck/ip_address_check.c +index b80990302a..a84aadaf73 100644 +--- a/testing/programs/ipcheck/ip_address_check.c ++++ b/testing/programs/ipcheck/ip_address_check.c +@@ -24,79 +24,76 @@ + #include "ip_address.h" + #include "ipcheck.h" + +-static void check_shunk_to_address(void) ++static void check_ttoaddress_num(void) + { + static const struct test { + int line; + int family; + const char *in; + const char *str; +- bool requires_dns; + } tests[] = { + + /* unset */ +- { LN, 0, "", NULL, false, }, ++ { LN, 0, "", NULL, }, + + /* any */ +- { LN, 4, "0.0.0.0", "0.0.0.0", false, }, +- { LN, 6, "::", "::", false, }, +- { LN, 6, "0:0:0:0:0:0:0:0", "::", false, }, ++ { LN, 4, "0.0.0.0", "0.0.0.0", }, ++ { LN, 6, "::", "::", }, ++ { LN, 6, "0:0:0:0:0:0:0:0", "::", }, + + /* local (zero's fill) */ +- { LN, 4, "127.1", "127.0.0.1", false, }, +- { LN, 4, "127.0.1", "127.0.0.1", false, }, +- { LN, 4, "127.0.0.1", "127.0.0.1", false, }, +- { LN, 6, "::1", "::1", false, }, +- { LN, 6, "0:0:0:0:0:0:0:1", "::1", false, }, ++ { LN, 4, "127.1", "127.0.0.1", }, ++ { LN, 4, "127.0.1", "127.0.0.1", }, ++ { LN, 4, "127.0.0.1", "127.0.0.1", }, ++ { LN, 6, "::1", "::1", }, ++ { LN, 6, "0:0:0:0:0:0:0:1", "::1", }, + + /* mask - and buffer overflow */ +- { LN, 4, "255.255.255.255", "255.255.255.255", false, }, +- { LN, 6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", false, }, ++ { LN, 4, "255.255.255.255", "255.255.255.255", }, ++ { LN, 6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", }, + + /* all bytes */ +- { LN, 4, "1.2.3.4", "1.2.3.4", false, }, +- { LN, 6, "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8", false, }, ++ { LN, 4, "1.2.3.4", "1.2.3.4", }, ++ { LN, 6, "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8", }, + + /* last digit is a big num - see wikepedia */ +- { LN, 4, "127.254", "127.0.0.254", false, }, +- { LN, 4, "127.65534", "127.0.255.254", false, }, +- { LN, 4, "127.16777214", "127.255.255.254", false, }, ++ { LN, 4, "127.254", "127.0.0.254", }, ++ { LN, 4, "127.65534", "127.0.255.254", }, ++ { LN, 4, "127.16777214", "127.255.255.254", }, + /* last digit overflow */ +- { LN, 4, "127.16777216", NULL, false, }, +- { LN, 4, "127.0.65536", NULL, false, }, +- { LN, 4, "127.0.0.256", NULL, false, }, ++ { LN, 4, "127.16777216", NULL, }, ++ { LN, 4, "127.0.65536", NULL, }, ++ { LN, 4, "127.0.0.256", NULL, }, + + /* suppress leading zeros - 01 vs 1 */ +- { LN, 6, "0001:0012:0003:0014:0005:0016:0007:0018", "1:12:3:14:5:16:7:18", false, }, ++ { LN, 6, "0001:0012:0003:0014:0005:0016:0007:0018", "1:12:3:14:5:16:7:18", }, + /* drop leading 0:0: */ +- { LN, 6, "0:0:3:4:5:6:7:8", "::3:4:5:6:7:8", false, }, ++ { LN, 6, "0:0:3:4:5:6:7:8", "::3:4:5:6:7:8", }, + /* drop middle 0:...:0 */ +- { LN, 6, "1:2:0:0:0:0:7:8", "1:2::7:8", false, }, ++ { LN, 6, "1:2:0:0:0:0:7:8", "1:2::7:8", }, + /* drop trailing :0..:0 */ +- { LN, 6, "1:2:3:4:5:0:0:0", "1:2:3:4:5::", false, }, ++ { LN, 6, "1:2:3:4:5:0:0:0", "1:2:3:4:5::", }, + /* drop first 0:..:0 */ +- { LN, 6, "1:2:0:0:5:6:0:0", "1:2::5:6:0:0", false, }, ++ { LN, 6, "1:2:0:0:5:6:0:0", "1:2::5:6:0:0", }, + /* drop logest 0:..:0 */ +- { LN, 6, "0:0:3:0:0:0:7:8", "0:0:3::7:8", false, }, ++ { LN, 6, "0:0:3:0:0:0:7:8", "0:0:3::7:8", }, + /* need two 0 */ +- { LN, 6, "0:2:0:4:0:6:0:8", "0:2:0:4:0:6:0:8", false, }, +- +- { LN, 4, "www.libreswan.org", "188.127.201.229", .requires_dns = true, }, ++ { LN, 6, "0:2:0:4:0:6:0:8", "0:2:0:4:0:6:0:8", }, + + /* hex/octal */ +- { LN, 4, "0x01.0x02.0x03.0x04", "1.2.3.4", false, }, +- { LN, 4, "0001.0002.0003.0004", "1.2.3.4", false, }, +- { LN, 4, "0x01020304", "1.2.3.4", false, }, ++ { LN, 4, "0x01.0x02.0x03.0x04", "1.2.3.4", }, ++ { LN, 4, "0001.0002.0003.0004", "1.2.3.4", }, ++ { LN, 4, "0x01020304", "1.2.3.4", }, + + /* trailing garbage */ +- { LN, 4, "1.2.3.4.", NULL, false, }, +- { LN, 4, "1.2.3.4a", NULL, false, }, +- { LN, 4, "1.2.3.0a", NULL, false, }, ++ { LN, 4, "1.2.3.4.", NULL, }, ++ { LN, 4, "1.2.3.4a", NULL, }, ++ { LN, 4, "1.2.3.0a", NULL, }, + + /* bad digits */ +- { LN, 4, "256.2.3.4", NULL, false, }, +- { LN, 4, "0008.2.3.4", NULL, false, }, +- { LN, 4, "0x0g.2.3.4", NULL, false, }, ++ { LN, 4, "256.2.3.4", NULL, }, ++ { LN, 4, "0008.2.3.4", NULL, }, ++ { LN, 4, "0x0g.2.3.4", NULL, }, + + }; + +@@ -104,66 +101,146 @@ static void check_shunk_to_address(void) + + for (size_t ti = 0; ti < elemsof(tests); ti++) { + const struct test *t = &tests[ti]; +- PRINT("%s '%s' -> str: '%s' dns: %s", pri_family(t->family), t->in, +- t->str == NULL ? "ERROR" : t->str, +- bool_str(t->requires_dns)); +- +- ip_address tmp, *address = &tmp; +- +- /* NUMERIC/NULL */ + +- FOR_EACH_THING(family, 0, t->family) { ++ /* ++ * For each address, perform lookups: ++ * ++ * - first with a generic family and then with the ++ * specified family ++ * ++ * - first with ttoaddress_num() and then ++ * ttoaddress_dns() (but only when it should work) ++ */ ++ ++ FOR_EACH_THING(family, 0, 4, 6) { + const struct ip_info *afi = IP_TYPE(family); +- err = ttoaddress_num(shunk1(t->in), afi, address); +- if (err != NULL) { +- if (t->str != NULL && !t->requires_dns) { +- FAIL("ttoaddress_num(%s, %s) unexpecedly failed: %s", +- t->in, pri_family(family), err); ++ bool err_expected = (t->str == NULL || (family != 0 && family != t->family)); ++ ++ struct lookup { ++ const char *name; ++ err_t (*ttoaddress)(shunk_t, const struct ip_info *, ip_address *); ++ bool need_dns; ++ } lookups[] = { ++ { ++ "ttoaddress_num", ++ ttoaddress_num, ++ false, ++ }, ++ { ++ "ttoaddress_dns", ++ ttoaddress_dns, ++ true, ++ }, ++ { ++ .name = NULL, ++ }, ++ }; ++ for (struct lookup *lookup = lookups; lookup->name != NULL; lookup++) { ++ ++ /* ++ * Without DNS a ++ * ttoaddress_dns() lookup of ++ * a bogus IP address will go ++ * into the weeds. ++ */ ++ bool skip = (lookup->need_dns && have_dns != DNS_YES); ++ ++ PRINT("%s('%s', %s) -> '%s'%s", ++ lookup->name, t->in, pri_family(family), ++ err_expected ? "ERROR" : t->str, ++ skip ? "; skipped as no DNS" : ""); ++ ++ if (skip) { ++ continue; ++ } ++ ++ ip_address tmp, *address = &tmp; ++ err = lookup->ttoaddress(shunk1(t->in), afi, address); ++ if (err_expected) { ++ if (err == NULL) { ++ FAIL("%s(%s, %s) unexpecedly succeeded", ++ lookup->name, t->in, pri_family(family)); ++ } ++ PRINT("%s(%s, %s) returned: %s", ++ lookup->name, t->in, pri_family(family), err); ++ } else if (err != NULL) { ++ FAIL("%s(%s, %s) unexpecedly failed: %s", ++ lookup->name, t->in, pri_family(family), err); + } else { +- PRINT("ttoaddress_num(%s, %s) returned: %s", +- t->in, pri_family(family), err); ++ CHECK_STR2(address); + } +- } else if (t->requires_dns) { +- FAIL("ttoaddress_num(%s, %s) unexpecedly parsed a DNS address", +- t->in, pri_family(family)); +- } else if (t->str == NULL) { +- FAIL("ttoaddress_num(%s, %s) unexpecedly succeeded", +- t->in, pri_family(family)); +- } else { +- CHECK_TYPE(address); + } + } ++ } ++} ++ ++static void check_ttoaddress_dns(void) ++{ ++ static const struct test { ++ int line; ++ int family; ++ const char *in; ++ const char *str; ++ bool need_dns; ++ } tests[] = { ++ ++ /* localhost is found in /etc/hosts on all platforms */ ++ { LN, 0, "localhost", "127.0.0.1", false, }, ++ { LN, 4, "localhost", "127.0.0.1", false, }, ++ { LN, 6, "localhost", "::1", false, }, ++ ++ { LN, 0, "www.libreswan.org", "188.127.201.229", true, }, ++ { LN, 4, "www.libreswan.org", "188.127.201.229", true, }, ++ { LN, 6, "www.libreswan.org", "2a00:1190:c00a:f00::229", true, }, + +- /* DNS/TYPE */ ++ { LN, 0, "nowhere.libreswan.org", NULL, true, }, ++ { LN, 4, "nowhere.libreswan.org", NULL, true, }, ++ { LN, 6, "nowhere.libreswan.org", NULL, true, }, + +- if (t->requires_dns && !use_dns) { +- PRINT("skipping dns_hunk_to_address(type) -- no DNS"); ++ }; ++ ++ err_t err; ++ ++ for (size_t ti = 0; ti < elemsof(tests); ti++) { ++ const struct test *t = &tests[ti]; ++ const struct ip_info *afi = IP_TYPE(t->family); ++ bool skip = (have_dns == DNS_NO || (have_dns != DNS_YES && t->need_dns)); ++ ++ PRINT("%s '%s' -> str: '%s' lookup: %s%s", ++ pri_family(t->family), t->in, ++ t->str == NULL ? "ERROR" : t->str, ++ (t->need_dns ? "DNS" : "/etc/hosts"), ++ (skip ? "; skipped as no DNS" : "")); ++ ++ if (skip) { ++ continue; ++ } ++ ++ ip_address tmp, *address = &tmp; ++ err = ttoaddress_dns(shunk1(t->in), afi, address); ++ if (err != NULL) { ++ if (t->str != NULL) { ++ FAIL("ttoaddress_dns(%s, %s) unexpecedly failed: %s", ++ t->in, pri_family(t->family), err); ++ } ++ PRINT("ttoaddress_dns(%s, %s) failed as expected: %s", ++ t->in, pri_family(t->family), err); ++ } else if (t->str == NULL) { ++ address_buf b; ++ FAIL("ttoaddress_dns(%s, %s) unexpecedly succeeded with %s", ++ t->in, pri_family(t->family), ++ str_address(address, &b)); + } else { +- const struct ip_info *afi = IP_TYPE(t->family); +- err = ttoaddress_dns(shunk1(t->in), afi, address); +- if (err != NULL) { +- if (t->str != NULL) { +- FAIL("ttoaddress_dns(%s, %s) unexpecedly failed: %s", +- t->in, pri_family(t->family), err); +- } else { +- PRINT("ttoaddress_dns(%s, %s) returned: %s", +- t->in, pri_family(t->family), err); +- } +- } else if (t->str == NULL) { +- FAIL("ttoaddress_dns(%s, %s) unexpecedly succeeded", +- t->in, pri_family(t->family)); +- } else { ++ address_buf b; ++ PRINT("ttoaddress_dns(%s, %s) succeeded with %s", ++ t->in, pri_family(t->family), ++ str_address(address, &b)); ++ if (t->family != 0) { + CHECK_TYPE(address); + } +- } +- +- /* now convert it back cooked */ +- if (t->requires_dns && !use_dns) { +- PRINT("skipping str_*() -- no DNS"); +- } else if (t->str != NULL) { ++ /* and back */ + CHECK_STR2(address); + } +- + } + } + +@@ -473,7 +550,8 @@ static void check_addresses_to(void) + + void ip_address_check(void) + { +- check_shunk_to_address(); ++ check_ttoaddress_num(); ++ check_ttoaddress_dns(); + check_str_address_sensitive(); + check_str_address_reversed(); + check_address_is(); +diff --git a/testing/programs/ipcheck/ip_info_check.c b/testing/programs/ipcheck/ip_info_check.c +index a7553a6029..f1566f4607 100644 +--- a/testing/programs/ipcheck/ip_info_check.c ++++ b/testing/programs/ipcheck/ip_info_check.c +@@ -31,10 +31,12 @@ + /*hack*/const typeof(L##_tests[0]) *t = &L##_tests[tl]; \ + /*hack*/size_t ti = tl; \ + const ip_##L *l = L##_tests[tl].L; \ +- if (l == NULL) continue; \ ++ if (l == NULL) \ ++ continue; \ + for (size_t tr = 0; tr < elemsof(R##_tests); tr++) { \ + const ip_##R *r = R##_tests[tr].R; \ +- if (r == NULL) continue; \ ++ if (r == NULL) \ ++ continue; \ + bool expected = false; \ + for (size_t to = 0; to < elemsof(L##_op_##R); to++) { \ + const typeof(L##_op_##R[0]) *op = &L##_op_##R[to]; \ +diff --git a/testing/programs/ipcheck/ip_range_check.c b/testing/programs/ipcheck/ip_range_check.c +index 256cf76c70..9f9a27db58 100644 +--- a/testing/programs/ipcheck/ip_range_check.c ++++ b/testing/programs/ipcheck/ip_range_check.c +@@ -389,7 +389,7 @@ static void check_range_op_range(void) + FAIL("ttorange(%s) failed: %s", t->R, oops); \ + } \ + } else { \ +- l = unset_range; \ ++ R = unset_range; \ + } + TT(l); + TT(r); +diff --git a/testing/programs/ipcheck/ip_sockaddr_check.c b/testing/programs/ipcheck/ip_sockaddr_check.c +index 538154b6e6..d9affb54f9 100644 +--- a/testing/programs/ipcheck/ip_sockaddr_check.c ++++ b/testing/programs/ipcheck/ip_sockaddr_check.c +@@ -20,6 +20,8 @@ + #include "ip_info.h" + #include "ip_protocol.h" + ++#include "lswlog.h" /* for DBG_dump_thing() */ ++ + #include "ipcheck.h" + + static void check_sockaddr_as_endpoint(void) +@@ -52,20 +54,25 @@ static void check_sockaddr_as_endpoint(void) + PRINT("%s '%s' -> '%s' len=%zd", pri_family(t->family), t->in, expect_out, t->size); + + /* construct a raw sockaddr */ +- ip_sockaddr sa = { +- .sa.sa = { +- .sa_family = SA_FAMILY(t->family), +- }, ++ ip_sockaddr sa = { + .len = t->size, + }; + switch (t->family) { + case 4: + memcpy(&sa.sa.sin.sin_addr, t->addr, sizeof(sa.sa.sin.sin_addr)); ++ sa.sa.sin.sin_family = AF_INET; + sa.sa.sin.sin_port = htons(t->port); ++#ifdef NEED_SIN_LEN ++ sa.sa.sin.sin_len = sizeof(struct sockaddr_in); ++#endif + break; + case 6: + memcpy(&sa.sa.sin6.sin6_addr, t->addr, sizeof(sa.sa.sin6.sin6_addr)); ++ sa.sa.sin6.sin6_family = AF_INET6; + sa.sa.sin6.sin6_port = htons(t->port); ++#ifdef NEED_SIN_LEN ++ sa.sa.sin6.sin6_len = sizeof(struct sockaddr_in6); ++#endif + break; + } + +@@ -107,6 +114,8 @@ static void check_sockaddr_as_endpoint(void) + esa.len, sizeof(esa.sa)); + } else if (!memeq(&esa.sa, &sa.sa, sizeof(esa.sa))) { + /* compare the entire buffer, not just size */ ++ DBG_dump_thing("esa.sa", esa.sa); ++ DBG_dump_thing("sa.sa", sa.sa); + FAIL("endpoint_to_sockaddr() returned a different value"); + } + } else { +diff --git a/testing/programs/ipcheck/ipcheck.c b/testing/programs/ipcheck/ipcheck.c +index ed13d1ed5c..8df45b5fd4 100644 +--- a/testing/programs/ipcheck/ipcheck.c ++++ b/testing/programs/ipcheck/ipcheck.c +@@ -25,21 +25,37 @@ + #include "lswtool.h" + + unsigned fails; +-bool use_dns = true; ++enum have_dns have_dns = DNS_NO; + + int main(int argc, char *argv[]) + { +- struct logger *logger = tool_init_log(argv[0]); ++ leak_detective = true; + log_ip = false; /* force sensitive */ ++ struct logger *logger = tool_init_log(argv[0]); ++ ++ if (argc != 2) { ++ fprintf(stderr, "usage: %s --dns={no,hosts-file,yes}\n", argv[0]); ++ return 1; ++ } ++ ++ /* only one option for now */ ++ const char *dns = argv[1]; ++ if (!eat(dns, "--dns")) { ++ fprintf(stderr, "%s: unknown option '%s'\n", ++ argv[0], argv[1]); ++ return 1; ++ } + +- for (char **argp = argv+1; argp < argv+argc; argp++) { +- if (streq(*argp, "--nodns")) { +- use_dns = false; +- } else { +- fprintf(stderr, "%s: unknown option '%s'\n", +- argv[0], *argp); +- return 1; +- } ++ if (streq(dns, "=no")) { ++ have_dns = DNS_NO; ++ } else if (streq(dns, "=hosts-file") || streq(dns, "")) { ++ have_dns = HAVE_HOSTS_FILE; ++ } else if (streq(dns, "=yes")) { ++ have_dns = DNS_YES; ++ } else { ++ fprintf(stderr, "%s: unknown --dns param '%s'\n", ++ argv[0], dns); ++ return 1; + } + + ip_address_check(); +@@ -55,6 +71,10 @@ int main(int argc, char *argv[]) + ip_port_range_check(); + ip_cidr_check(); + ++ report_leaks(logger); ++ ++ ++ + if (fails > 0) { + fprintf(stderr, "TOTAL FAILURES: %d\n", fails); + return 1; +diff --git a/testing/programs/ipcheck/ipcheck.h b/testing/programs/ipcheck/ipcheck.h +index 7e7c2a284b..5cfdbf05f7 100644 +--- a/testing/programs/ipcheck/ipcheck.h ++++ b/testing/programs/ipcheck/ipcheck.h +@@ -44,7 +44,7 @@ extern void ip_cidr_check(void); + */ + + extern unsigned fails; +-extern bool use_dns; ++extern enum have_dns { DNS_NO, HAVE_HOSTS_FILE, DNS_YES, } have_dns; + + #define pri_family(FAMILY) ((FAMILY) == 0 ? "0" : \ + (FAMILY) == 4 ? "IPv4" : \ diff --git a/libreswan.spec b/libreswan.spec index c370831..bac512b 100644 --- a/libreswan.spec +++ b/libreswan.spec @@ -41,6 +41,8 @@ Source2: https://download.libreswan.org/cavs/ikev1_psk.fax.bz2 Source3: https://download.libreswan.org/cavs/ikev2.fax.bz2 %endif +Patch1: libreswan-4.4-ipcheck.patch + BuildRequires: audit-libs-devel BuildRequires: bison BuildRequires: curl-devel @@ -95,6 +97,7 @@ Libreswan is based on Openswan-2.6.38 which in turn is based on FreeS/WAN-2.04 %setup -q -n libreswan-%{version}%{?prever} # enable crypto-policies support sed -i "s:#[ ]*include \(.*\)\(/crypto-policies/back-ends/libreswan.config\)$:include \1\2:" configs/ipsec.conf.in +%patch1 -p1 %build make %{?_smp_mflags} \