mirror of
https://github.com/openbsd/src.git
synced 2026-06-18 07:13:36 +02:00
unit test for new servconf.[ch] code, including a basic fuzz
test for deserialisation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $
|
||||
# $OpenBSD: Makefile,v 1.14 2026/05/31 11:39:44 djm Exp $
|
||||
|
||||
SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion
|
||||
SUBDIR+=authopt misc sshsig
|
||||
SUBDIR+=authopt misc sshsig servconf
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# $OpenBSD: Makefile,v 1.1 2026/05/31 11:39:44 djm Exp $
|
||||
|
||||
PROG=test_servconf
|
||||
SRCS=tests.c
|
||||
|
||||
SRCS+=servconf.c groupaccess.c
|
||||
|
||||
# From usr.bin/ssh
|
||||
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
|
||||
SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
|
||||
SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
|
||||
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
|
||||
SRCS+=addr.c addrmatch.c bitmap.c
|
||||
SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
|
||||
SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c
|
||||
SRCS+=utf8.c ssherr-libcrypto.c
|
||||
SRCS+=kex.c kex-names.c packet.c dispatch.c compat.c canohost.c
|
||||
SRCS+=digest-openssl.c ed25519-openssl.c
|
||||
|
||||
REGRESS_TARGETS=run-regress-${PROG}
|
||||
|
||||
run-regress-${PROG}: ${PROG}
|
||||
env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS}
|
||||
|
||||
.include <bsd.regress.mk>
|
||||
@@ -0,0 +1,362 @@
|
||||
/* $OpenBSD: tests.c,v 1.1 2026/05/31 11:39:44 djm Exp $ */
|
||||
/*
|
||||
* Regress tests for servconf.h server configuration API
|
||||
*
|
||||
* Placed in the public domain
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../test_helper/test_helper.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "servconf.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
struct sshbuf *cfg;
|
||||
|
||||
/* stub */
|
||||
int auth2_methods_valid(const char *methods, int need_enable);
|
||||
int
|
||||
auth2_methods_valid(const char *methods, int need_enable)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
onerror(void *fuzz)
|
||||
{
|
||||
fprintf(stderr, "Failed during fuzz:\n");
|
||||
fuzz_dump((struct fuzz *)fuzz);
|
||||
}
|
||||
|
||||
static void
|
||||
set_string(char **dst, const char *s)
|
||||
{
|
||||
*dst = s == NULL ? NULL : xstrdup(s);
|
||||
}
|
||||
|
||||
static char **
|
||||
new_string_array(u_int n)
|
||||
{
|
||||
return xcalloc(n, sizeof(char *));
|
||||
}
|
||||
|
||||
static void
|
||||
set_test_options(ServerOptions *o)
|
||||
{
|
||||
initialize_server_options(o);
|
||||
|
||||
o->num_ports = 2;
|
||||
o->ports[0] = 22;
|
||||
o->ports[1] = 2022;
|
||||
o->ip_qos_interactive = 0x10;
|
||||
o->ip_qos_bulk = 0x08;
|
||||
o->log_facility = SYSLOG_FACILITY_AUTH;
|
||||
o->log_level = SYSLOG_LEVEL_DEBUG3;
|
||||
o->fwd_opts.gateway_ports = 1;
|
||||
o->fwd_opts.streamlocal_bind_mask = 0177;
|
||||
o->fwd_opts.streamlocal_bind_unlink = 1;
|
||||
o->permit_user_env = 1;
|
||||
set_string(&o->permit_user_env_allowlist, "");
|
||||
o->rekey_limit = 123456789;
|
||||
o->rekey_interval = 600;
|
||||
o->timing_secret = 0x0102030405060708ULL;
|
||||
|
||||
set_string(&o->routing_domain, "");
|
||||
set_string(&o->banner, NULL);
|
||||
set_string(&o->adm_forced_command, "internal-sftp");
|
||||
set_string(&o->chroot_directory, "");
|
||||
set_string(&o->host_key_agent, NULL);
|
||||
set_string(&o->authorized_keys_command, "/bin/echo");
|
||||
set_string(&o->authorized_keys_command_user, "");
|
||||
set_string(&o->authorized_principals_file, NULL);
|
||||
|
||||
o->num_authkeys_files = 3;
|
||||
o->authorized_keys_files = new_string_array(o->num_authkeys_files);
|
||||
set_string(&o->authorized_keys_files[0], NULL);
|
||||
set_string(&o->authorized_keys_files[1], "");
|
||||
set_string(&o->authorized_keys_files[2], ".ssh/authorized_keys");
|
||||
|
||||
o->num_log_verbose = 2;
|
||||
o->log_verbose = new_string_array(o->num_log_verbose);
|
||||
set_string(&o->log_verbose[0], NULL);
|
||||
set_string(&o->log_verbose[1], "kex.c:*");
|
||||
|
||||
o->num_host_key_files = 3;
|
||||
o->host_key_file_userprovided =
|
||||
xcalloc(o->num_host_key_files,
|
||||
sizeof(*o->host_key_file_userprovided));
|
||||
o->host_key_files = new_string_array(o->num_host_key_files);
|
||||
o->host_key_file_userprovided[0] = 0;
|
||||
o->host_key_file_userprovided[1] = 1;
|
||||
o->host_key_file_userprovided[2] = -1;
|
||||
set_string(&o->host_key_files[0], NULL);
|
||||
set_string(&o->host_key_files[1], "");
|
||||
set_string(&o->host_key_files[2], "/tmp/ssh_host_ed25519_key");
|
||||
|
||||
o->num_queued_listens = 2;
|
||||
o->queued_listen_addrs = xcalloc(o->num_queued_listens,
|
||||
sizeof(*o->queued_listen_addrs));
|
||||
set_string(&o->queued_listen_addrs[0].addr, "127.0.0.1");
|
||||
o->queued_listen_addrs[0].port = 2222;
|
||||
set_string(&o->queued_listen_addrs[0].rdomain, NULL);
|
||||
set_string(&o->queued_listen_addrs[1].addr, "::1");
|
||||
o->queued_listen_addrs[1].port = -1;
|
||||
set_string(&o->queued_listen_addrs[1].rdomain, "");
|
||||
|
||||
o->num_subsystems = 2;
|
||||
o->subsystem_name = new_string_array(o->num_subsystems);
|
||||
o->subsystem_command = new_string_array(o->num_subsystems);
|
||||
o->subsystem_args = new_string_array(o->num_subsystems);
|
||||
set_string(&o->subsystem_name[0], "sftp");
|
||||
set_string(&o->subsystem_command[0], "internal-sftp");
|
||||
set_string(&o->subsystem_args[0], "internal-sftp -f AUTH");
|
||||
set_string(&o->subsystem_name[1], "echo");
|
||||
set_string(&o->subsystem_command[1], "/bin/echo");
|
||||
set_string(&o->subsystem_args[1], "/bin/echo hello");
|
||||
}
|
||||
|
||||
static void
|
||||
check_roundtrip(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
ServerOptions out;
|
||||
|
||||
initialize_server_options(&out);
|
||||
ASSERT_INT_EQ(serialise_server_options(o, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
ASSERT_INT_EQ(deserialise_server_options(buf, &out), 0);
|
||||
ASSERT_SIZE_T_EQ(sshbuf_len(buf), 0);
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_ports, 2);
|
||||
ASSERT_INT_EQ(out.ports[0], 22);
|
||||
ASSERT_INT_EQ(out.ports[1], 2022);
|
||||
ASSERT_INT_EQ(out.ip_qos_interactive, 0x10);
|
||||
ASSERT_INT_EQ(out.ip_qos_bulk, 0x08);
|
||||
ASSERT_INT_EQ(out.log_facility, SYSLOG_FACILITY_AUTH);
|
||||
ASSERT_INT_EQ(out.log_level, SYSLOG_LEVEL_DEBUG3);
|
||||
ASSERT_INT_EQ(out.fwd_opts.gateway_ports, 1);
|
||||
ASSERT_INT_EQ(out.fwd_opts.streamlocal_bind_mask, 0177);
|
||||
ASSERT_INT_EQ(out.fwd_opts.streamlocal_bind_unlink, 1);
|
||||
ASSERT_INT_EQ(out.permit_user_env, 1);
|
||||
ASSERT_STRING_EQ(out.permit_user_env_allowlist, "");
|
||||
ASSERT_LONG_LONG_EQ(out.rekey_limit, 123456789);
|
||||
ASSERT_INT_EQ(out.rekey_interval, 600);
|
||||
ASSERT_U64_EQ(out.timing_secret, 0x0102030405060708ULL);
|
||||
|
||||
ASSERT_STRING_EQ(out.routing_domain, "");
|
||||
ASSERT_PTR_EQ(out.banner, NULL);
|
||||
ASSERT_STRING_EQ(out.adm_forced_command, "internal-sftp");
|
||||
ASSERT_STRING_EQ(out.chroot_directory, "");
|
||||
ASSERT_PTR_EQ(out.host_key_agent, NULL);
|
||||
ASSERT_STRING_EQ(out.authorized_keys_command, "/bin/echo");
|
||||
ASSERT_STRING_EQ(out.authorized_keys_command_user, "");
|
||||
ASSERT_PTR_EQ(out.authorized_principals_file, NULL);
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_authkeys_files, 3);
|
||||
ASSERT_PTR_EQ(out.authorized_keys_files[0], NULL);
|
||||
ASSERT_STRING_EQ(out.authorized_keys_files[1], "");
|
||||
ASSERT_STRING_EQ(out.authorized_keys_files[2], ".ssh/authorized_keys");
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_log_verbose, 2);
|
||||
ASSERT_PTR_EQ(out.log_verbose[0], NULL);
|
||||
ASSERT_STRING_EQ(out.log_verbose[1], "kex.c:*");
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_host_key_files, 3);
|
||||
ASSERT_INT_EQ(out.host_key_file_userprovided[0], 0);
|
||||
ASSERT_INT_EQ(out.host_key_file_userprovided[1], 1);
|
||||
ASSERT_INT_EQ(out.host_key_file_userprovided[2], -1);
|
||||
ASSERT_PTR_EQ(out.host_key_files[0], NULL);
|
||||
ASSERT_STRING_EQ(out.host_key_files[1], "");
|
||||
ASSERT_STRING_EQ(out.host_key_files[2], "/tmp/ssh_host_ed25519_key");
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_queued_listens, 2);
|
||||
ASSERT_STRING_EQ(out.queued_listen_addrs[0].addr, "127.0.0.1");
|
||||
ASSERT_INT_EQ(out.queued_listen_addrs[0].port, 2222);
|
||||
ASSERT_PTR_EQ(out.queued_listen_addrs[0].rdomain, NULL);
|
||||
ASSERT_STRING_EQ(out.queued_listen_addrs[1].addr, "::1");
|
||||
ASSERT_INT_EQ(out.queued_listen_addrs[1].port, -1);
|
||||
ASSERT_STRING_EQ(out.queued_listen_addrs[1].rdomain, "");
|
||||
|
||||
ASSERT_U_INT_EQ(out.num_subsystems, 2);
|
||||
ASSERT_STRING_EQ(out.subsystem_name[0], "sftp");
|
||||
ASSERT_STRING_EQ(out.subsystem_command[0], "internal-sftp");
|
||||
ASSERT_STRING_EQ(out.subsystem_args[0], "internal-sftp -f AUTH");
|
||||
ASSERT_STRING_EQ(out.subsystem_name[1], "echo");
|
||||
ASSERT_STRING_EQ(out.subsystem_command[1], "/bin/echo");
|
||||
ASSERT_STRING_EQ(out.subsystem_args[1], "/bin/echo hello");
|
||||
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_rejects_trailing_data(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
ServerOptions out;
|
||||
int r;
|
||||
|
||||
initialize_server_options(&out);
|
||||
ASSERT_INT_EQ(serialise_server_options(o, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
ASSERT_INT_EQ(sshbuf_put_u8(buf, 0), 0);
|
||||
r = deserialise_server_options(buf, &out);
|
||||
ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT);
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_rejects_bad_version(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
ServerOptions out;
|
||||
int r;
|
||||
|
||||
initialize_server_options(&out);
|
||||
ASSERT_INT_EQ(serialise_server_options(o, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
ASSERT_PTR_NE(sshbuf_mutable_ptr(buf), NULL);
|
||||
POKE_U32(sshbuf_mutable_ptr(buf), 2);
|
||||
r = deserialise_server_options(buf, &out);
|
||||
ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT);
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_rejects_bad_port_count(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
ServerOptions out;
|
||||
int r;
|
||||
|
||||
initialize_server_options(&out);
|
||||
ASSERT_INT_EQ(serialise_server_options(o, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
ASSERT_SIZE_T_GT(sshbuf_len(buf), 8);
|
||||
ASSERT_PTR_NE(sshbuf_mutable_ptr(buf), NULL);
|
||||
POKE_U32(sshbuf_mutable_ptr(buf) + 4, MAX_PORTS + 1);
|
||||
r = deserialise_server_options(buf, &out);
|
||||
ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT);
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_roundtrip_signed_limits(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
ServerOptions out, in;
|
||||
|
||||
initialize_server_options(&out);
|
||||
in = *o;
|
||||
in.fwd_opts.streamlocal_bind_mask = (mode_t)-1;
|
||||
in.ip_qos_bulk = INT_MIN;
|
||||
in.rekey_limit = INT64_MIN;
|
||||
ASSERT_INT_EQ(serialise_server_options(&in, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
ASSERT_INT_EQ(deserialise_server_options(buf, &out), 0);
|
||||
ASSERT_INT_EQ(out.fwd_opts.streamlocal_bind_mask == (mode_t)-1, 1);
|
||||
ASSERT_INT_EQ(out.ip_qos_bulk, INT_MIN);
|
||||
ASSERT_LONG_LONG_EQ(out.rekey_limit, INT64_MIN);
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
attempt_deserialise_blob(const u_char *p, size_t len)
|
||||
{
|
||||
struct sshbuf *buf;
|
||||
ServerOptions out;
|
||||
|
||||
initialize_server_options(&out);
|
||||
ASSERT_PTR_NE(buf = sshbuf_from(p, len), NULL);
|
||||
(void)deserialise_server_options(buf, &out);
|
||||
free_server_options(&out);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_fuzz_deserialise(const ServerOptions *o)
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
struct fuzz *fuzz;
|
||||
u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
|
||||
FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
|
||||
|
||||
if (test_is_fast())
|
||||
fuzzers &= ~FUZZ_1_BIT_FLIP;
|
||||
if (test_is_slow())
|
||||
fuzzers |= FUZZ_2_BYTE_FLIP;
|
||||
|
||||
ASSERT_INT_EQ(serialise_server_options(o, &buf), 0);
|
||||
ASSERT_PTR_NE(buf, NULL);
|
||||
fuzz = fuzz_begin(fuzzers, sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
TEST_ONERROR(onerror, fuzz);
|
||||
for (; !fuzz_done(fuzz); fuzz_next(fuzz))
|
||||
attempt_deserialise_blob(fuzz_ptr(fuzz), fuzz_len(fuzz));
|
||||
TEST_ONERROR(NULL, NULL);
|
||||
fuzz_cleanup(fuzz);
|
||||
sshbuf_free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
tests(void)
|
||||
{
|
||||
ServerOptions o;
|
||||
|
||||
log_init("test_servconf", SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_AUTH, 1);
|
||||
|
||||
TEST_START("server options round trip preserves nullable state");
|
||||
set_test_options(&o);
|
||||
check_roundtrip(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
|
||||
TEST_START("server options reject trailing data");
|
||||
set_test_options(&o);
|
||||
check_rejects_trailing_data(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
|
||||
TEST_START("server options reject unsupported version");
|
||||
set_test_options(&o);
|
||||
check_rejects_bad_version(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
|
||||
TEST_START("server options reject bad port count");
|
||||
set_test_options(&o);
|
||||
check_rejects_bad_port_count(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
|
||||
TEST_START("server options round trip signed limits");
|
||||
set_test_options(&o);
|
||||
check_roundtrip_signed_limits(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
|
||||
TEST_START("server options deserialise fuzz");
|
||||
set_test_options(&o);
|
||||
check_fuzz_deserialise(&o);
|
||||
free_server_options(&o);
|
||||
TEST_DONE();
|
||||
}
|
||||
|
||||
void
|
||||
benchmarks(void)
|
||||
{
|
||||
printf("no benchmarks\n");
|
||||
}
|
||||
Reference in New Issue
Block a user