2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00
bind/tests/isc/proxyheader_test.c
Ondřej Surý f5c204ac3e
Move the library init and shutdown to executables
Instead of relying on unreliable order of execution of the library
constructors and destructors, move them to individual binaries.  The
advantage is that the execution time and order will remain constant and
will not depend on the dynamic load dependency solver.

This requires more work, but that was mitigated by a simple requirement,
any executable using libisc and libdns, must include <isc/lib.h> and
<dns/lib.h> respectively (in this particular order).  In turn, these two
headers must not be included from within any library as they contain
inlined functions marked with constructor/destructor attributes.
2025-02-22 16:19:00 +01:00

1211 lines
40 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/buffer.h>
#include <isc/lib.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/proxy2.h>
#include <isc/random.h>
#include "proxyheader_test_data.h"
#include <tests/isc.h>
typedef struct dummy_handler_cbarg {
isc_proxy2_command_t cmd;
int socktype;
isc_sockaddr_t src_addr;
isc_sockaddr_t dst_addr;
size_t no_more_calls;
size_t tlvs;
size_t tls_subtlvs;
uint8_t tls_client_flags;
bool client_cert_verified;
isc_region_t tlv_data;
isc_region_t extra;
isc_region_t tls_version;
isc_region_t tls_common_name;
} dummy_handler_cbarg_t;
static bool
dummy_subtlv_iter_cb(const uint8_t client, const bool client_cert_verified,
const isc_proxy2_tlv_subtype_tls_t tls_subtlv_type,
const isc_region_t *restrict data, void *cbarg) {
dummy_handler_cbarg_t *arg = (dummy_handler_cbarg_t *)cbarg;
UNUSED(client);
UNUSED(client_cert_verified);
arg->tls_subtlvs++;
switch (tls_subtlv_type) {
case ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION:
arg->tls_version = *data;
break;
case ISC_PROXY2_TLV_SUBTYPE_TLS_CN:
arg->tls_common_name = *data;
break;
default:
break;
};
return true;
}
static bool
dummy_tlv_iter_cb(const isc_proxy2_tlv_type_t tlv_type,
const isc_region_t *restrict data, void *cbarg) {
dummy_handler_cbarg_t *arg = (dummy_handler_cbarg_t *)cbarg;
if (arg != NULL) {
arg->tlvs++;
}
if (tlv_type == ISC_PROXY2_TLV_TYPE_TLS) {
isc_result_t result = isc_proxy2_subtlv_tls_header_data(
data, &arg->tls_client_flags,
&arg->client_cert_verified);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_subtlv_tls_iterate(
data, dummy_subtlv_iter_cb, cbarg);
assert_true(result == ISC_R_SUCCESS);
}
return true;
}
static void
proxy2_handler_dummy(const isc_result_t result, const isc_proxy2_command_t cmd,
const int socktype,
const isc_sockaddr_t *restrict src_addr,
const isc_sockaddr_t *restrict dst_addr,
const isc_region_t *restrict tlv_blob,
const isc_region_t *restrict extra, void *cbarg) {
dummy_handler_cbarg_t *arg = (dummy_handler_cbarg_t *)cbarg;
UNUSED(extra);
if (result == ISC_R_NOMORE && arg != NULL) {
arg->no_more_calls++;
return;
} else if (result != ISC_R_SUCCESS) {
return;
}
if (cmd == ISC_PROXY2_CMD_PROXY && socktype != 0 /* unspec */) {
INSIST(src_addr != NULL);
INSIST(dst_addr != NULL);
} else if (cmd == ISC_PROXY2_CMD_LOCAL) {
INSIST(tlv_blob == NULL);
INSIST(src_addr == NULL);
INSIST(dst_addr == NULL);
}
if (arg != NULL) {
arg->cmd = cmd;
arg->socktype = socktype;
if (src_addr != NULL) {
INSIST(dst_addr != NULL);
arg->src_addr = *src_addr;
arg->dst_addr = *dst_addr;
}
}
if (tlv_blob) {
assert_true(isc_proxy2_tlv_data_verify(tlv_blob) ==
ISC_R_SUCCESS);
if (cbarg != NULL) {
isc_proxy2_tlv_iterate(tlv_blob, dummy_tlv_iter_cb,
cbarg);
}
}
}
static int
setup_test_proxy(void **state) {
isc_proxy2_handler_t **handler = (isc_proxy2_handler_t **)state;
*handler = isc_proxy2_handler_new(mctx, 0, proxy2_handler_dummy, NULL);
return 0;
}
static int
teardown_test_proxy(void **state) {
isc_proxy2_handler_free((isc_proxy2_handler_t **)state);
return 0;
}
static void
test_header_data(isc_proxy2_handler_t *handler, const void *data,
const size_t size, const bool tear_apart,
const bool tear_randomly) {
isc_region_t region = { 0 };
isc_result_t result;
if (tear_apart) {
isc_buffer_t databuf = { 0 };
isc_buffer_init(&databuf, (void *)data, size);
isc_buffer_add(&databuf, size);
for (; isc_buffer_remaininglength(&databuf) > 0;) {
isc_region_t remaining = { 0 };
size_t sz = 1;
if (tear_randomly) {
sz = 1 + isc_random_uniform(
isc_buffer_remaininglength(
&databuf));
}
isc_buffer_remainingregion(&databuf, &remaining);
remaining.length = sz;
result = isc_proxy2_handler_push(handler, &remaining);
assert_true(isc_proxy2_handler_result(handler) ==
result);
isc_buffer_forward(&databuf, sz);
if (result == ISC_R_SUCCESS) {
break;
}
}
} else {
result = isc_proxy2_handler_push_data(handler, data, size);
assert_true(isc_proxy2_handler_result(handler) == result);
}
assert_true(isc_proxy2_handler_result(handler) == ISC_R_SUCCESS);
isc_proxy2_handler_header(handler, &region);
assert_true(region.length == size);
assert_true(memcmp(region.base, data, region.length) == 0);
}
static void
verify_proxy_v2_header(isc_proxy2_handler_t *handler,
dummy_handler_cbarg_t *cbarg) {
char sabuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
isc_sockaddr_t src_addr = { 0 }, dst_addr = { 0 };
isc_result_t result;
int socktype = -1;
assert_true(cbarg->cmd == ISC_PROXY2_CMD_PROXY);
assert_true(cbarg->socktype == SOCK_STREAM);
assert_true(isc_sockaddr_pf(&cbarg->dst_addr) == AF_INET);
assert_true(isc_sockaddr_pf(&cbarg->src_addr) == AF_INET);
isc_sockaddr_format(&cbarg->dst_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.66#11883") == 0);
isc_sockaddr_format(&cbarg->src_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.1#56784") == 0);
if (handler != NULL) {
result = isc_proxy2_handler_addresses(handler, &socktype,
&src_addr, &dst_addr);
assert_true(result == ISC_R_SUCCESS);
assert_true(isc_sockaddr_equal(&src_addr, &cbarg->src_addr));
assert_true(isc_sockaddr_equal(&dst_addr, &cbarg->dst_addr));
assert_true(socktype == cbarg->socktype);
}
assert_true(cbarg->tlvs == 0);
assert_true(cbarg->tls_subtlvs == 0);
assert_true(cbarg->tls_client_flags == 0);
assert_true(cbarg->client_cert_verified == false);
}
static void
verify_proxy_v2_header_with_TLS(isc_proxy2_handler_t *handler,
dummy_handler_cbarg_t *cbarg) {
char sabuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
isc_sockaddr_t src_addr = { 0 }, dst_addr = { 0 };
isc_result_t result;
int socktype = -1;
assert_true(cbarg->cmd == ISC_PROXY2_CMD_PROXY);
assert_true(cbarg->socktype == SOCK_STREAM);
assert_true(isc_sockaddr_pf(&cbarg->dst_addr) == AF_INET);
assert_true(isc_sockaddr_pf(&cbarg->src_addr) == AF_INET);
isc_sockaddr_format(&cbarg->dst_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.67#11883") == 0);
isc_sockaddr_format(&cbarg->src_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.1#39754") == 0);
if (handler != NULL) {
result = isc_proxy2_handler_addresses(handler, &socktype,
&src_addr, &dst_addr);
assert_true(result == ISC_R_SUCCESS);
assert_true(isc_sockaddr_equal(&src_addr, &cbarg->src_addr));
assert_true(isc_sockaddr_equal(&dst_addr, &cbarg->dst_addr));
assert_true(socktype == cbarg->socktype);
}
assert_true(cbarg->tlvs == 1);
assert_true(cbarg->tls_subtlvs == 1);
assert_true(cbarg->tls_client_flags == ISC_PROXY2_CLIENT_TLS);
assert_true(cbarg->client_cert_verified == true);
/* "TLSv1.2" (w/o trailing '\0') */
assert_true(cbarg->tls_version.length == 7);
assert_true(memcmp(cbarg->tls_version.base, "TLSv1.2", 7) == 0);
}
static void
verify_proxy_v2_header_with_TLS_CN(isc_proxy2_handler_t *handler,
dummy_handler_cbarg_t *cbarg) {
char sabuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
isc_sockaddr_t src_addr = { 0 }, dst_addr = { 0 };
isc_result_t result;
int socktype = -1;
assert_true(cbarg->cmd == ISC_PROXY2_CMD_PROXY);
assert_true(cbarg->socktype == SOCK_STREAM);
assert_true(isc_sockaddr_pf(&cbarg->dst_addr) == AF_INET);
assert_true(isc_sockaddr_pf(&cbarg->src_addr) == AF_INET);
isc_sockaddr_format(&cbarg->dst_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.67#11883") == 0);
isc_sockaddr_format(&cbarg->src_addr, sabuf, sizeof(sabuf));
assert_true(strcmp(sabuf, "127.0.0.1#40402") == 0);
if (handler != NULL) {
result = isc_proxy2_handler_addresses(handler, &socktype,
&src_addr, &dst_addr);
assert_true(result == ISC_R_SUCCESS);
assert_true(isc_sockaddr_equal(&src_addr, &cbarg->src_addr));
assert_true(isc_sockaddr_equal(&dst_addr, &cbarg->dst_addr));
assert_true(socktype == cbarg->socktype);
}
assert_true(cbarg->tlvs == 1);
assert_true(cbarg->tls_subtlvs == 2); /* version and common name */
assert_true(cbarg->tls_client_flags ==
(ISC_PROXY2_CLIENT_TLS | ISC_PROXY2_CLIENT_CERT_SESS |
ISC_PROXY2_CLIENT_CERT_CONN));
assert_true(cbarg->client_cert_verified == true);
/* "TLSv1.2" (w/o trailing '\0') */
assert_true(cbarg->tls_version.length == 7);
assert_true(memcmp(cbarg->tls_version.base, "TLSv1.2", 7) == 0);
/* "mqttuser1" (w/o trailing '\0') */
assert_true(cbarg->tls_common_name.length == 9);
assert_true(memcmp(cbarg->tls_common_name.base, "mqttuser1", 9) == 0);
}
static void
verify_proxy_v2_header_with_AF_UNIX(isc_proxy2_handler_t *handler,
dummy_handler_cbarg_t *cbarg) {
assert_true(cbarg->cmd == ISC_PROXY2_CMD_PROXY);
assert_true(cbarg->socktype == 0);
if (handler != NULL) {
int socktype = -1;
isc_result_t result;
result = isc_proxy2_handler_addresses(handler, &socktype, NULL,
NULL);
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(socktype, 0);
}
}
ISC_RUN_TEST_IMPL(proxyheader_generic_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
dummy_handler_cbarg_t cbarg = { 0 };
isc_proxy2_handler_setcb(handler, proxy2_handler_dummy, &cbarg);
test_header_data(handler, proxy_v2_header, sizeof(proxy_v2_header),
false, false);
verify_proxy_v2_header(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS,
sizeof(proxy_v2_header_with_TLS), false, false);
verify_proxy_v2_header_with_TLS(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS_CN,
sizeof(proxy_v2_header_with_TLS_CN), false, false);
verify_proxy_v2_header_with_TLS_CN(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_AF_UNIX,
sizeof(proxy_v2_header_with_AF_UNIX), false, false);
verify_proxy_v2_header_with_AF_UNIX(handler, &cbarg);
}
ISC_RUN_TEST_IMPL(proxyheader_generic_byte_by_byte_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
dummy_handler_cbarg_t cbarg = { 0 };
isc_proxy2_handler_setcb(handler, proxy2_handler_dummy, &cbarg);
test_header_data(handler, proxy_v2_header, sizeof(proxy_v2_header),
true, false);
verify_proxy_v2_header(handler, &cbarg);
assert_true(cbarg.no_more_calls == sizeof(proxy_v2_header) - 1);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS,
sizeof(proxy_v2_header_with_TLS), true, false);
verify_proxy_v2_header_with_TLS(handler, &cbarg);
assert_true(cbarg.no_more_calls ==
sizeof(proxy_v2_header_with_TLS) - 1);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS_CN,
sizeof(proxy_v2_header_with_TLS_CN), true, false);
verify_proxy_v2_header_with_TLS_CN(handler, &cbarg);
assert_true(cbarg.no_more_calls ==
sizeof(proxy_v2_header_with_TLS_CN) - 1);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_AF_UNIX,
sizeof(proxy_v2_header_with_AF_UNIX), true, false);
verify_proxy_v2_header_with_AF_UNIX(handler, &cbarg);
assert_true(cbarg.no_more_calls ==
sizeof(proxy_v2_header_with_AF_UNIX) - 1);
}
ISC_RUN_TEST_IMPL(proxyheader_generic_torn_apart_randomly_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
dummy_handler_cbarg_t cbarg = { 0 };
isc_proxy2_handler_setcb(handler, proxy2_handler_dummy, &cbarg);
test_header_data(handler, proxy_v2_header, sizeof(proxy_v2_header),
true, true);
verify_proxy_v2_header(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS,
sizeof(proxy_v2_header_with_TLS), true, true);
verify_proxy_v2_header_with_TLS(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_TLS_CN,
sizeof(proxy_v2_header_with_TLS_CN), true, true);
verify_proxy_v2_header_with_TLS_CN(handler, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
test_header_data(handler, (void *)proxy_v2_header_with_AF_UNIX,
sizeof(proxy_v2_header_with_AF_UNIX), true, true);
verify_proxy_v2_header_with_AF_UNIX(handler, &cbarg);
}
ISC_RUN_TEST_IMPL(proxyheader_direct_test) {
isc_result_t result;
isc_region_t region = { 0 };
dummy_handler_cbarg_t cbarg = { 0 };
cbarg = (dummy_handler_cbarg_t){ 0 };
region.base = (uint8_t *)proxy_v2_header;
region.length = sizeof(proxy_v2_header);
result = isc_proxy2_header_handle_directly(
&region, proxy2_handler_dummy, &cbarg);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.no_more_calls == 0);
verify_proxy_v2_header(NULL, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
region.base = (uint8_t *)proxy_v2_header_with_TLS;
region.length = sizeof(proxy_v2_header_with_TLS);
result = isc_proxy2_header_handle_directly(
&region, proxy2_handler_dummy, &cbarg);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.no_more_calls == 0);
isc_proxy2_tlv_iterate(&cbarg.tlv_data, dummy_tlv_iter_cb, &cbarg);
verify_proxy_v2_header_with_TLS(NULL, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
region.base = (uint8_t *)proxy_v2_header_with_TLS_CN;
region.length = sizeof(proxy_v2_header_with_TLS_CN);
result = isc_proxy2_header_handle_directly(
&region, proxy2_handler_dummy, &cbarg);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.no_more_calls == 0);
isc_proxy2_tlv_iterate(&cbarg.tlv_data, dummy_tlv_iter_cb, &cbarg);
verify_proxy_v2_header_with_TLS_CN(NULL, &cbarg);
cbarg = (dummy_handler_cbarg_t){ 0 };
region.base = (uint8_t *)proxy_v2_header_with_AF_UNIX;
region.length = sizeof(proxy_v2_header_with_AF_UNIX);
result = isc_proxy2_header_handle_directly(
&region, proxy2_handler_dummy, &cbarg);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.no_more_calls == 0);
verify_proxy_v2_header_with_AF_UNIX(NULL, &cbarg);
}
ISC_RUN_TEST_IMPL(proxyheader_detect_bad_signature_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
for (size_t i = 0; i < ISC_PROXY2_HEADER_SIGNATURE_SIZE; i++) {
isc_result_t result;
uint8_t sig[ISC_PROXY2_HEADER_SIGNATURE_SIZE];
memmove(sig, ISC_PROXY2_HEADER_SIGNATURE,
ISC_PROXY2_HEADER_SIGNATURE_SIZE);
sig[i] = 0x0C; /* it is not present in the valid signature */
/*
* We are expected to detect bad signature as early as possible,
* so we are passing only a part of the header.
*/
result = isc_proxy2_handler_push_data(handler, sig, i + 1);
assert_true(result == ISC_R_UNEXPECTED);
}
}
ISC_RUN_TEST_IMPL(proxyheader_extra_data_test) {
isc_result_t result;
isc_buffer_t databuf;
isc_region_t region = { 0 };
size_t sz;
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
uint8_t header[] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00, 0x0d, 0x0a, 0x51,
0x55, 0x49, 0x54, 0x0a, 0x21, 0x11, 0x00, 0x1e,
0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x43,
0x9b, 0x4a, 0x2e, 0x6b, 0x20, 0x00, 0x0f, 0x01,
0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x07, 0x54,
0x4c, 0x53, 0x76, 0x31, 0x2e, 0x32 };
uint8_t extra_data[] = { 0x10, 0x1a, 0x00, 0x04, 0x4d, 0x51, 0x54,
0x54, 0x04, 0x02, 0x00, 0x3c, 0x00, 0x0e,
0x4d, 0x51, 0x54, 0x54, 0x5f, 0x46, 0x58,
0x5f, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74 };
uint8_t data[sizeof(header) + sizeof(extra_data)];
isc_buffer_init(&databuf, (void *)data, sizeof(data));
isc_buffer_putmem(&databuf, header, sizeof(header));
isc_buffer_putmem(&databuf, extra_data, sizeof(extra_data));
isc_buffer_remainingregion(&databuf, &region);
result = isc_proxy2_handler_push(handler, &region);
assert_true(result == ISC_R_SUCCESS);
region = (isc_region_t){ 0 };
sz = isc_proxy2_handler_header(handler, &region);
assert_true(sz == sizeof(header));
assert_true(sz == region.length);
assert_true(memcmp(header, region.base, sz) == 0);
region = (isc_region_t){ 0 };
sz = isc_proxy2_handler_extra(handler, &region);
assert_true(sz == sizeof(extra_data));
assert_true(sz == region.length);
assert_true(memcmp(extra_data, region.base, sz) == 0);
}
ISC_RUN_TEST_IMPL(proxyheader_max_size_test) {
isc_result_t result;
isc_proxy2_handler_t handler;
UNUSED(state);
isc_proxy2_handler_init(&handler, mctx, sizeof(proxy_v2_header),
proxy2_handler_dummy, NULL);
result = isc_proxy2_handler_push_data(&handler, proxy_v2_header,
sizeof(proxy_v2_header));
assert_true(result == ISC_R_SUCCESS);
isc_proxy2_handler_uninit(&handler);
isc_proxy2_handler_init(&handler, mctx, sizeof(proxy_v2_header) - 1,
proxy2_handler_dummy, NULL);
result = isc_proxy2_handler_push_data(&handler, proxy_v2_header,
sizeof(proxy_v2_header));
assert_true(result == ISC_R_RANGE);
isc_proxy2_handler_uninit(&handler);
}
ISC_RUN_TEST_IMPL(proxyheader_make_header_test) {
isc_result_t result;
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
isc_buffer_t databuf;
uint8_t data[ISC_PROXY2_MAX_SIZE];
isc_buffer_t sslbuf;
uint8_t ssldata[ISC_PROXY2_MAX_SIZE];
isc_region_t region = { 0 };
uint8_t extra[256] = { 0 };
const char *tls_version = "TLSv1.3";
const char *tls_cn = "name.test";
dummy_handler_cbarg_t cbarg = { 0 };
struct in_addr localhost4 = { 0 };
isc_sockaddr_t src_addrv4 = { 0 }, dst_addrv4 = { 0 },
src_addrv6 = { 0 }, dst_addrv6 = { 0 };
const uint16_t src_port = 1236;
const uint16_t dst_port = 9582;
localhost4.s_addr = htonl(INADDR_LOOPBACK);
isc_sockaddr_fromin(&src_addrv4, &localhost4, src_port);
isc_sockaddr_fromin(&dst_addrv4, &localhost4, dst_port);
isc_sockaddr_fromin6(&src_addrv6, &in6addr_loopback, src_port);
isc_sockaddr_fromin6(&dst_addrv6, &in6addr_loopback, dst_port);
isc_proxy2_handler_setcb(handler, proxy2_handler_dummy, &cbarg);
isc_buffer_init(&databuf, (void *)data, sizeof(data));
isc_buffer_init(&sslbuf, (void *)ssldata, sizeof(ssldata));
/* unspec */
result = isc_proxy2_make_header(&databuf, ISC_PROXY2_CMD_LOCAL, 0, NULL,
NULL, NULL);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == ISC_PROXY2_HEADER_SIZE);
region = (isc_region_t){ .base = extra, .length = sizeof(extra) };
result = isc_proxy2_header_append_tlv(
&databuf, ISC_PROXY2_TLV_TYPE_NOOP, &region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == ISC_PROXY2_HEADER_SIZE + sizeof(extra) +
ISC_PROXY2_TLV_HEADER_SIZE);
result = isc_proxy2_handler_push(handler, &region);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.tlvs == 0); /* in unspec mode we ignore TLVs */
/* AF_INET, SOCK_STREAM */
cbarg = (dummy_handler_cbarg_t){ 0 };
isc_buffer_clear(&databuf);
result = isc_proxy2_make_header(&databuf, ISC_PROXY2_CMD_PROXY,
SOCK_STREAM, &src_addrv4, &dst_addrv4,
NULL);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == ISC_PROXY2_MIN_AF_INET_SIZE);
region = (isc_region_t){ .base = extra, .length = sizeof(extra) };
result = isc_proxy2_header_append_tlv(
&databuf, ISC_PROXY2_TLV_TYPE_NOOP, &region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == ISC_PROXY2_MIN_AF_INET_SIZE +
sizeof(extra) +
ISC_PROXY2_TLV_HEADER_SIZE);
result = isc_proxy2_handler_push(handler, &region);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.tlvs == 1); /* ISC_PROXY2_TLV_TYPE_NOOP */
assert_true(cbarg.socktype == SOCK_STREAM);
assert_true(isc_sockaddr_pf(&cbarg.src_addr) == AF_INET);
assert_true(isc_sockaddr_pf(&cbarg.dst_addr) == AF_INET);
assert_true(isc_sockaddr_equal(&cbarg.src_addr, &src_addrv4));
assert_true(isc_sockaddr_equal(&cbarg.dst_addr, &dst_addrv4));
/* AF_INET6, SOCK_STREAM (+ TLS version and CN) */
cbarg = (dummy_handler_cbarg_t){ 0 };
isc_buffer_clear(&databuf);
result = isc_proxy2_make_header(&databuf, ISC_PROXY2_CMD_PROXY,
SOCK_STREAM, &src_addrv6, &dst_addrv6,
NULL);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == ISC_PROXY2_MIN_AF_INET6_SIZE);
region = (isc_region_t){ .base = extra, .length = sizeof(extra) };
result = isc_proxy2_header_append_tlv(
&databuf, ISC_PROXY2_TLV_TYPE_NOOP, &region);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_make_tls_subheader(
&sslbuf, ISC_PROXY2_CLIENT_TLS | ISC_PROXY2_CLIENT_CERT_CONN,
true, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&sslbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, tls_version);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&sslbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_CN, tls_cn);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&sslbuf, &region);
result = isc_proxy2_header_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
size_t expected = ISC_PROXY2_MIN_AF_INET6_SIZE + sizeof(extra) +
(4 * ISC_PROXY2_TLV_HEADER_SIZE) +
ISC_PROXY2_TLS_SUBHEADER_MIN_SIZE +
strlen(tls_version) + strlen(tls_cn);
assert_true(region.length == expected);
result = isc_proxy2_handler_push(handler, &region);
assert_true(result == ISC_R_SUCCESS);
assert_true(cbarg.socktype == SOCK_STREAM);
assert_true(isc_sockaddr_pf(&cbarg.src_addr) == AF_INET6);
assert_true(isc_sockaddr_pf(&cbarg.dst_addr) == AF_INET6);
assert_true(isc_sockaddr_equal(&cbarg.src_addr, &src_addrv6));
assert_true(isc_sockaddr_equal(&cbarg.dst_addr, &dst_addrv6));
region = (isc_region_t){ 0 };
(void)isc_proxy2_handler_tlvs(handler, &region);
assert_true(isc_proxy2_tlv_data_verify(&region) == ISC_R_SUCCESS);
/* ISC_PROXY2_TLV_TYPE_NOOP+ISC_PROXY2_TLV_TYPE_TLS */
assert_true(cbarg.tlvs == 2);
/* ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION+ISC_PROXY2_TLV_SUBTYPE_TLS_CN */
assert_true(cbarg.tls_subtlvs == 2);
assert_true(cbarg.tls_version.length == strlen(tls_version));
assert_true(memcmp(cbarg.tls_version.base, tls_version,
strlen(tls_version)) == 0);
assert_true(cbarg.tls_common_name.length == strlen(tls_cn));
assert_true(memcmp(cbarg.tls_common_name.base, tls_cn,
strlen(tls_cn)) == 0);
}
static bool
rebuild_subtlv_iter_cb(const uint8_t client, const bool client_cert_verified,
const isc_proxy2_tlv_subtype_tls_t tls_subtlv_type,
const isc_region_t *restrict data, void *cbarg) {
isc_result_t result;
isc_buffer_t *outbuf = (isc_buffer_t *)cbarg;
UNUSED(client);
UNUSED(client_cert_verified);
result = isc_proxy2_append_tlv(outbuf, tls_subtlv_type, data);
assert_true(result == ISC_R_SUCCESS);
return true;
}
static bool
rebuild_tlv_iter_cb(const isc_proxy2_tlv_type_t tlv_type,
const isc_region_t *restrict data, void *cbarg) {
isc_result_t result;
isc_buffer_t *outbuf = (isc_buffer_t *)cbarg;
if (tlv_type == ISC_PROXY2_TLV_TYPE_TLS) {
uint8_t client_flags = 0;
bool client_cert_verified = false;
isc_buffer_t databuf = { 0 };
isc_region_t region = { 0 };
uint8_t storage[ISC_PROXY2_MAX_SIZE];
isc_buffer_init(&databuf, (void *)storage, sizeof(storage));
/* get flags values */
result = isc_proxy2_subtlv_tls_header_data(
data, &client_flags, &client_cert_verified);
assert_true(result == ISC_R_SUCCESS);
/* create header */
result = isc_proxy2_make_tls_subheader(
&databuf, client_flags, client_cert_verified, NULL);
assert_true(result == ISC_R_SUCCESS);
/* process and append values */
result = isc_proxy2_subtlv_tls_iterate(
data, rebuild_subtlv_iter_cb, &databuf);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_header_append_tlv(outbuf, tlv_type,
&region);
assert_true(result == ISC_R_SUCCESS);
} else {
result = isc_proxy2_header_append_tlv(outbuf, tlv_type, data);
assert_true(result == ISC_R_SUCCESS);
}
return true;
}
static void
proxy2_handler_rebuild_cb(const isc_result_t header_result,
const isc_proxy2_command_t cmd, const int socktype,
const isc_sockaddr_t *restrict src_addr,
const isc_sockaddr_t *restrict dst_addr,
const isc_region_t *restrict tlv_blob,
const isc_region_t *restrict extra, void *cbarg) {
isc_result_t result;
isc_buffer_t *outbuf = (isc_buffer_t *)cbarg;
if (header_result != ISC_R_SUCCESS) {
return;
}
result = isc_proxy2_make_header(outbuf, cmd, socktype, src_addr,
dst_addr, NULL);
assert_true(result == ISC_R_SUCCESS);
if (tlv_blob != NULL) {
isc_proxy2_tlv_iterate(tlv_blob, rebuild_tlv_iter_cb, outbuf);
}
if (extra != NULL) {
result = isc_proxy2_tlv_data_verify(tlv_blob);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_putmem(outbuf, extra->base, extra->length);
}
}
static void
proxy2_handler_rebuild(isc_buffer_t *restrict outbuf, const void *data,
const size_t size) {
isc_proxy2_handler_t handler = { 0 };
isc_proxy2_handler_init(&handler, mctx, 0, proxy2_handler_rebuild_cb,
outbuf);
isc_proxy2_handler_push_data(&handler, data, size);
isc_proxy2_handler_uninit(&handler);
}
static void
try_rebuild_header(const void *data, size_t size) {
isc_buffer_t databuf = { 0 };
isc_region_t region = { 0 };
uint8_t storage[ISC_PROXY2_MAX_SIZE];
isc_buffer_init(&databuf, (void *)storage, sizeof(storage));
proxy2_handler_rebuild(&databuf, data, size);
isc_buffer_usedregion(&databuf, &region);
assert_true(region.length == size);
assert_true(memcmp(region.base, data, size) == 0);
}
ISC_RUN_TEST_IMPL(proxyheader_rebuild_header_test) {
try_rebuild_header(proxy_v2_header, sizeof(proxy_v2_header));
try_rebuild_header(proxy_v2_header_with_TLS,
sizeof(proxy_v2_header_with_TLS));
try_rebuild_header(proxy_v2_header_with_TLS_CN,
sizeof(proxy_v2_header_with_TLS_CN));
}
ISC_RUN_TEST_IMPL(proxyheader_bad_header_signature_test) {
size_t i;
isc_result_t result;
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
for (i = 0; i < ISC_PROXY2_HEADER_SIGNATURE_SIZE; i++) {
uint8_t sig[ISC_PROXY2_HEADER_SIGNATURE_SIZE];
memmove(sig, ISC_PROXY2_HEADER_SIGNATURE,
ISC_PROXY2_HEADER_SIGNATURE_SIZE);
sig[i] = 0x0C; /* 0x0C cannot be found in the signature */
result = isc_proxy2_handler_push_data(handler, sig,
sizeof(sig));
assert_true(result == ISC_R_UNEXPECTED);
isc_proxy2_handler_clear(handler);
}
result = isc_proxy2_handler_push_data(handler,
ISC_PROXY2_HEADER_SIGNATURE,
ISC_PROXY2_HEADER_SIGNATURE_SIZE);
assert_true(result == ISC_R_NOMORE);
}
ISC_RUN_TEST_IMPL(proxyheader_bad_proto_version_command_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
isc_result_t result;
uint8_t *pver_cmd = NULL;
uint8_t botched_header[sizeof(proxy_v2_header)] = { 0 };
memmove(botched_header, proxy_v2_header, sizeof(proxy_v2_header));
pver_cmd = &botched_header[ISC_PROXY2_HEADER_SIGNATURE_SIZE];
assert_true(*pver_cmd == 0x21);
*pver_cmd = 0x31; /* unexpected version (3) followed by PROXY command */
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_NOTIMPLEMENTED);
*pver_cmd = 0x22; /* version two followed by unexpected command (2) */
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_UNEXPECTED);
}
ISC_RUN_TEST_IMPL(proxyheader_bad_family_socktype_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
isc_result_t result;
uint8_t *pfam = NULL;
uint8_t botched_header[sizeof(proxy_v2_header)] = { 0 };
memmove(botched_header, proxy_v2_header, sizeof(proxy_v2_header));
pfam = &botched_header[ISC_PROXY2_HEADER_SIGNATURE_SIZE + 1];
assert_true(*pfam == 0x11);
*pfam = 0x41; /* unexpected family (4) followed by SOCK_STREAM (1)*/
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_UNEXPECTED);
*pfam = 0x13; /* AF_INET (1) followed by unexpected sock type (3) */
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_UNEXPECTED);
}
static inline void
update_header_length(uint8_t *botched_header, uint16_t newlen) {
newlen = htons(newlen);
memmove(&botched_header[ISC_PROXY2_HEADER_SIGNATURE_SIZE + 2], &newlen,
sizeof(newlen));
}
ISC_RUN_TEST_IMPL(proxyheader_bad_unexpected_not_enough_length_test) {
isc_proxy2_handler_t *handler = (isc_proxy2_handler_t *)*state;
isc_result_t result;
uint8_t botched_header[sizeof(proxy_v2_header)] = { 0 };
memmove(botched_header, proxy_v2_header, sizeof(proxy_v2_header));
update_header_length(botched_header, 0);
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_RANGE);
update_header_length(botched_header, 4); /* not enough */
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_RANGE);
update_header_length(botched_header, UINT16_MAX); /* no more */
result = isc_proxy2_handler_push_data(handler, botched_header,
sizeof(botched_header));
assert_true(result == ISC_R_NOMORE);
isc_proxy2_handler_clear(handler);
}
ISC_RUN_TEST_IMPL(proxyheader_tlv_data_test) {
isc_result_t result;
isc_buffer_t databuf = { 0 };
isc_buffer_t tlsbuf = { 0 };
uint8_t data[ISC_PROXY2_MAX_SIZE] = { 0 };
uint8_t tlsdata[ISC_PROXY2_MAX_SIZE] = { 0 };
uint8_t zerodata[0xff] = { 0 };
isc_region_t region = { 0 };
const char *alpn = "dot";
const char *tls_version = "TLSv1.3";
const char *tls_cn = "name.test";
isc_buffer_init(&databuf, (void *)data, sizeof(data));
isc_buffer_init(&tlsbuf, (void *)tlsdata, sizeof(tlsdata));
/* zero filled data is not fine */
region.base = zerodata;
region.length = sizeof(zerodata);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* crc32c must be 4 bytes long */
isc_buffer_clear(&databuf);
region.base = (uint8_t *)zerodata;
region.length = sizeof(zerodata);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_CRC32C,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_RANGE);
isc_buffer_clear(&databuf);
region.base = (uint8_t *)zerodata;
region.length = 4;
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_CRC32C,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* unique id must be <= 128 bytes long */
isc_buffer_clear(&databuf);
region.base = (uint8_t *)zerodata;
region.length = sizeof(zerodata);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_UNIQUE_ID,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_RANGE);
isc_buffer_clear(&databuf);
region.base = (uint8_t *)zerodata;
region.length = 128;
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_UNIQUE_ID,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* two noops is fine */
isc_buffer_clear(&databuf);
region = (isc_region_t){ 0 };
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_NOOP,
&region);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_NOOP,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* one ALPN tag is fine */
isc_buffer_clear(&databuf);
result = isc_proxy2_append_tlv_string(&databuf,
ISC_PROXY2_TLV_TYPE_ALPN, alpn);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* two ALPN tags is not fine */
result = isc_proxy2_append_tlv_string(&databuf,
ISC_PROXY2_TLV_TYPE_ALPN, alpn);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* empty TLS subheader is tolerable */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, 0, false, NULL);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* empty TLS subheader with no TLS version while one is expected */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, ISC_PROXY2_CLIENT_TLS,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* TLS subheader with TLS version */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, ISC_PROXY2_CLIENT_TLS,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
region.length = sizeof(tls_version);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, tls_version);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_SUCCESS);
/* TLS subheader with multiple TLS versions is not fine */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, ISC_PROXY2_CLIENT_TLS,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, tls_version);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, &region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* TLS subheader with unexpected TLS version */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, 0, false, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, tls_version);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* TLS subheader with no CN while expected */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(
&tlsbuf, ISC_PROXY2_CLIENT_TLS | ISC_PROXY2_CLIENT_CERT_CONN,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_VERSION, tls_version);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* TLS subheader with unexpected CN */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(&tlsbuf, ISC_PROXY2_CLIENT_TLS,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_CN, tls_cn);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* TLS subheader with CN unexpected (because TLS flag is not set) */
isc_buffer_clear(&databuf);
isc_buffer_clear(&tlsbuf);
result = isc_proxy2_make_tls_subheader(
&tlsbuf,
ISC_PROXY2_CLIENT_CERT_CONN | ISC_PROXY2_CLIENT_CERT_SESS,
false, NULL);
assert_true(result == ISC_R_SUCCESS);
result = isc_proxy2_append_tlv_string(
&tlsbuf, ISC_PROXY2_TLV_SUBTYPE_TLS_CN, tls_cn);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&tlsbuf, &region);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_TLS,
&region);
assert_true(result == ISC_R_SUCCESS);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_UNEXPECTED);
/* botched TLV header */
isc_buffer_clear(&databuf);
region.base = (uint8_t *)zerodata;
region.length = sizeof(zerodata);
result = isc_proxy2_append_tlv(&databuf, ISC_PROXY2_TLV_TYPE_NOOP,
&region);
isc_buffer_subtract(&databuf, region.length / 2);
isc_buffer_usedregion(&databuf, &region);
result = isc_proxy2_tlv_data_verify(&region);
assert_true(result == ISC_R_RANGE);
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY_CUSTOM(proxyheader_generic_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_generic_byte_by_byte_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_generic_torn_apart_randomly_test,
setup_test_proxy, teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_direct_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_detect_bad_signature_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_extra_data_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_max_size_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_make_header_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_rebuild_header_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_bad_header_signature_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_bad_proto_version_command_test,
setup_test_proxy, teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_bad_family_socktype_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_bad_unexpected_not_enough_length_test,
setup_test_proxy, teardown_test_proxy)
ISC_TEST_ENTRY_CUSTOM(proxyheader_tlv_data_test, setup_test_proxy,
teardown_test_proxy)
ISC_TEST_LIST_END
ISC_TEST_MAIN