From 0892edaa3ce623381d3a7635544cbc69b31cf9cb Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 4 Mar 2016 02:30:36 +0000 Subject: upstream commit add KEX fuzzer harness; ok deraadt@ Upstream-Regress-ID: 3df5242d30551b12b828aa9ba4a4cec0846be8d1 --- regress/misc/kexfuzz/Makefile | 78 ++++++++ regress/misc/kexfuzz/README | 28 +++ regress/misc/kexfuzz/kexfuzz.c | 404 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 510 insertions(+) create mode 100644 regress/misc/kexfuzz/Makefile create mode 100644 regress/misc/kexfuzz/README create mode 100644 regress/misc/kexfuzz/kexfuzz.c (limited to 'regress/misc/kexfuzz') diff --git a/regress/misc/kexfuzz/Makefile b/regress/misc/kexfuzz/Makefile new file mode 100644 index 000000000..3018b632f --- /dev/null +++ b/regress/misc/kexfuzz/Makefile @@ -0,0 +1,78 @@ +# $OpenBSD: Makefile,v 1.1 2016/03/04 02:30:37 djm Exp $ + +.include +.include + +# XXX detect from ssh binary? +SSH1?= no +OPENSSL?= yes + +PROG= kexfuzz +SRCS= kexfuzz.c +NOMAN= 1 + +.if (${OPENSSL:L} == "yes") +CFLAGS+= -DWITH_OPENSSL +.else +# SSH v.1 requires OpenSSL. +SSH1= no +.endif + +.if (${SSH1:L} == "yes") +CFLAGS+= -DWITH_SSH1 +.endif + +# enable warnings +WARNINGS=Yes + +DEBUG=-g +CFLAGS+= -fstack-protector-all +CDIAGFLAGS= -Wall +CDIAGFLAGS+= -Wextra +CDIAGFLAGS+= -Werror +CDIAGFLAGS+= -Wchar-subscripts +CDIAGFLAGS+= -Wcomment +CDIAGFLAGS+= -Wformat +CDIAGFLAGS+= -Wformat-security +CDIAGFLAGS+= -Wimplicit +CDIAGFLAGS+= -Winline +CDIAGFLAGS+= -Wmissing-declarations +CDIAGFLAGS+= -Wmissing-prototypes +CDIAGFLAGS+= -Wparentheses +CDIAGFLAGS+= -Wpointer-arith +CDIAGFLAGS+= -Wreturn-type +CDIAGFLAGS+= -Wshadow +CDIAGFLAGS+= -Wsign-compare +CDIAGFLAGS+= -Wstrict-aliasing +CDIAGFLAGS+= -Wstrict-prototypes +CDIAGFLAGS+= -Wswitch +CDIAGFLAGS+= -Wtrigraphs +CDIAGFLAGS+= -Wuninitialized +CDIAGFLAGS+= -Wunused +.if ${COMPILER_VERSION} == "gcc4" +CDIAGFLAGS+= -Wpointer-sign +CDIAGFLAGS+= -Wold-style-definition +.endif + +SSHREL=../../../../../usr.bin/ssh + +CFLAGS+=-I${.CURDIR}/${SSHREL} + +.if exists(${.CURDIR}/${SSHREL}/lib/${__objdir}) +LDADD+=-L${.CURDIR}/${SSHREL}/lib/${__objdir} -lssh +DPADD+=${.CURDIR}/${SSHREL}/lib/${__objdir}/libssh.a +.else +LDADD+=-L${.CURDIR}/${SSHREL}/lib -lssh +DPADD+=${.CURDIR}/${SSHREL}/lib/libssh.a +.endif + +LDADD+= -lutil -lz +DPADD+= ${LIBUTIL} ${LIBZ} + +.if (${OPENSSL:L} == "yes") +LDADD+= -lcrypto +DPADD+= ${LIBCRYPTO} +.endif + +.include + diff --git a/regress/misc/kexfuzz/README b/regress/misc/kexfuzz/README new file mode 100644 index 000000000..8b215b5bf --- /dev/null +++ b/regress/misc/kexfuzz/README @@ -0,0 +1,28 @@ +This is a harness to help with fuzzing KEX. + +To use it, you first set it to count packets in each direction: + +./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key -c +S2C: 29 +C2S: 31 + +Then get it to record a particular packet (in this case the 4th +packet from client->server): + +./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \ + -d -D C2S -i 3 -f packet_3 + +Fuzz the packet somehow: + +dd if=/dev/urandom of=packet_3 bs=32 count=1 # Just for example + +Then re-run the key exchange substituting the modified packet in +its original sequence: + +./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \ + -r -D C2S -i 3 -f packet_3 + +A comprehensive KEX fuzz run would fuzz every packet in both +directions for each key exchange type and every hostkey type. +This will take some time. + diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c new file mode 100644 index 000000000..d57a117ac --- /dev/null +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -0,0 +1,404 @@ +/* $OpenBSD: kexfuzz.c,v 1.1 2016/03/04 02:30:37 djm Exp $ */ +/* + * Fuzz harness for KEX code + * + * Placed in the public domain + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ssherr.h" +#include "ssh_api.h" +#include "sshbuf.h" +#include "packet.h" +#include "myproposal.h" +#include "authfile.h" + +struct ssh *active_state = NULL; /* XXX - needed for linking */ + +void kex_tests(void); +static int do_debug = 0; + +enum direction { S2C, C2S }; + +static int +do_send_and_receive(struct ssh *from, struct ssh *to, int mydirection, + int *packet_count, int trigger_direction, int packet_index, + const char *dump_path, struct sshbuf *replace_data) +{ + u_char type; + size_t len, olen; + const u_char *buf; + int r; + FILE *dumpfile; + + for (;;) { + if ((r = ssh_packet_next(from, &type)) != 0) { + fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r)); + return r; + } + if (type != 0) + return 0; + buf = ssh_output_ptr(from, &len); + olen = len; + if (do_debug) { + printf("%s packet %d type %u len %zu:\n", + mydirection == S2C ? "s2c" : "c2s", + *packet_count, type, len); + sshbuf_dump_data(buf, len, stdout); + } + if (mydirection == trigger_direction && + packet_index == *packet_count) { + if (replace_data != NULL) { + buf = sshbuf_ptr(replace_data); + len = sshbuf_len(replace_data); + if (do_debug) { + printf("***** replaced packet " + "len %zu\n", len); + sshbuf_dump_data(buf, len, stdout); + } + } else if (dump_path != NULL) { + if ((dumpfile = fopen(dump_path, "w+")) == NULL) + err(1, "fopen %s", dump_path); + if (len != 0 && + fwrite(buf, len, 1, dumpfile) != 1) + err(1, "fwrite %s", dump_path); + if (do_debug) + printf("***** dumped packet " + "len %zu\n", len); + fclose(dumpfile); + exit(0); + } + } + (*packet_count)++; + if (len == 0) + return 0; + if ((r = ssh_input_append(to, buf, len)) != 0 || + (r = ssh_output_consume(from, olen)) != 0) + return r; + } +} + +/* Minimal test_helper.c scaffholding to make this standalone */ +const char *in_test = NULL; +#define TEST_START(a) \ + do { \ + in_test = (a); \ + if (do_debug) \ + fprintf(stderr, "test %s starting\n", in_test); \ + } while (0) +#define TEST_DONE() \ + do { \ + if (do_debug) \ + fprintf(stderr, "test %s done\n", \ + in_test ? in_test : "???"); \ + in_test = NULL; \ + } while(0) +#define ASSERT_INT_EQ(a, b) \ + do { \ + if ((int)(a) != (int)(b)) { \ + fprintf(stderr, "%s %s:%d " \ + "%s (%d) != expected %s (%d)\n", \ + in_test ? in_test : "(none)", \ + __func__, __LINE__, #a, (int)(a), #b, (int)(b)); \ + exit(2); \ + } \ + } while (0) +#define ASSERT_INT_GE(a, b) \ + do { \ + if ((int)(a) < (int)(b)) { \ + fprintf(stderr, "%s %s:%d " \ + "%s (%d) < expected %s (%d)\n", \ + in_test ? in_test : "(none)", \ + __func__, __LINE__, #a, (int)(a), #b, (int)(b)); \ + exit(2); \ + } \ + } while (0) +#define ASSERT_PTR_NE(a, b) \ + do { \ + if ((a) == (b)) { \ + fprintf(stderr, "%s %s:%d " \ + "%s (%p) != expected %s (%p)\n", \ + in_test ? in_test : "(none)", \ + __func__, __LINE__, #a, (a), #b, (b)); \ + exit(2); \ + } \ + } while (0) + + +static void +run_kex(struct ssh *client, struct ssh *server, int *s2c, int *c2s, + int direction, int packet_index, + const char *dump_path, struct sshbuf *replace_data) +{ + int r = 0; + + while (!server->kex->done || !client->kex->done) { + if ((r = do_send_and_receive(server, client, S2C, s2c, + direction, packet_index, dump_path, replace_data))) + break; + if ((r = do_send_and_receive(client, server, C2S, c2s, + direction, packet_index, dump_path, replace_data))) + break; + } + if (do_debug) + printf("done: %s\n", ssh_err(r)); + ASSERT_INT_EQ(r, 0); + ASSERT_INT_EQ(server->kex->done, 1); + ASSERT_INT_EQ(client->kex->done, 1); +} + +static void +do_kex_with_key(const char *kex, struct sshkey *prvkey, int *c2s, int *s2c, + int direction, int packet_index, + const char *dump_path, struct sshbuf *replace_data) +{ + struct ssh *client = NULL, *server = NULL, *server2 = NULL; + struct sshkey *pubkey = NULL; + struct sshbuf *state; + struct kex_params kex_params; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *keyname = NULL; + + TEST_START("sshkey_from_private"); + ASSERT_INT_EQ(sshkey_from_private(prvkey, &pubkey), 0); + TEST_DONE(); + + TEST_START("ssh_init"); + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = strdup(kex); + keyname = strdup(sshkey_ssh_name(prvkey)); + ASSERT_PTR_NE(keyname, NULL); + kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; + ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); + ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0); + ASSERT_PTR_NE(client, NULL); + ASSERT_PTR_NE(server, NULL); + TEST_DONE(); + + TEST_START("ssh_add_hostkey"); + ASSERT_INT_EQ(ssh_add_hostkey(server, prvkey), 0); + ASSERT_INT_EQ(ssh_add_hostkey(client, pubkey), 0); + TEST_DONE(); + + TEST_START("kex"); + run_kex(client, server, s2c, c2s, direction, packet_index, + dump_path, replace_data); + TEST_DONE(); + + TEST_START("rekeying client"); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server, s2c, c2s, direction, packet_index, + dump_path, replace_data); + TEST_DONE(); + + TEST_START("rekeying server"); + ASSERT_INT_EQ(kex_send_kexinit(server), 0); + run_kex(client, server, s2c, c2s, direction, packet_index, + dump_path, replace_data); + TEST_DONE(); + + TEST_START("ssh_packet_get_state"); + state = sshbuf_new(); + ASSERT_PTR_NE(state, NULL); + ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0); + ASSERT_INT_GE(sshbuf_len(state), 1); + TEST_DONE(); + + TEST_START("ssh_packet_set_state"); + server2 = NULL; + ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0); + ASSERT_PTR_NE(server2, NULL); + ASSERT_INT_EQ(ssh_add_hostkey(server2, prvkey), 0); + kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */ + ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0); + ASSERT_INT_EQ(sshbuf_len(state), 0); + sshbuf_free(state); + ASSERT_PTR_NE(server2->kex, NULL); + /* XXX we need to set the callbacks */ + server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +#ifdef OPENSSL_HAS_ECC + server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; +#endif + server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server; + server2->kex->load_host_public_key = server->kex->load_host_public_key; + server2->kex->load_host_private_key = server->kex->load_host_private_key; + server2->kex->sign = server->kex->sign; + TEST_DONE(); + + TEST_START("rekeying server2"); + ASSERT_INT_EQ(kex_send_kexinit(server2), 0); + run_kex(client, server2, s2c, c2s, direction, packet_index, + dump_path, replace_data); + ASSERT_INT_EQ(kex_send_kexinit(client), 0); + run_kex(client, server2, s2c, c2s, direction, packet_index, + dump_path, replace_data); + TEST_DONE(); + + TEST_START("cleanup"); + sshkey_free(pubkey); + ssh_free(client); + ssh_free(server); + ssh_free(server2); + free(keyname); + TEST_DONE(); +} + +static void +usage(void) +{ + fprintf(stderr, + "Usage: kexfuzz [-hcdrv] [-D direction] [-f data_file]\n" + " [-K kex_alg] [-k private_key] [-i packet_index]\n" + "\n" + "Options:\n" + " -h Display this help\n" + " -c Count packets sent during KEX\n" + " -d Dump mode: record KEX packet to data file\n" + " -r Replace mode: replace packet with data file\n" + " -v Turn on verbose logging\n" + " -D S2C|C2S Packet direction for replacement or dump\n" + " -f data_file Path to data file for replacement or dump\n" + " -K kex_alg Name of KEX algorithm to test (see below)\n" + " -k private_key Path to private key file\n" + " -i packet_index Index of packet to replace or dump (from 0)\n" + "\n" + "Available KEX algorithms: %s\n", kex_alg_list(' ')); +} + +static void +badusage(const char *bad) +{ + fprintf(stderr, "Invalid options\n"); + fprintf(stderr, "%s\n", bad); + usage(); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, fd, r; + int count_flag = 0, dump_flag = 0, replace_flag = 0; + int packet_index = -1, direction = -1; + int s2c = 0, c2s = 0; /* packet counts */ + const char *kex = NULL, *kpath = NULL, *data_path = NULL; + struct sshkey *key = NULL; + struct sshbuf *replace_data = NULL; + + setvbuf(stdout, NULL, _IONBF, 0); + while ((ch = getopt(argc, argv, "hcdrvD:f:K:k:i:")) != -1) { + switch (ch) { + case 'h': + usage(); + return 0; + case 'c': + count_flag = 1; + break; + case 'd': + dump_flag = 1; + break; + case 'r': + replace_flag = 1; + break; + case 'v': + do_debug = 1; + break; + + case 'D': + if (strcasecmp(optarg, "s2c") == 0) + direction = S2C; + else if (strcasecmp(optarg, "c2s") == 0) + direction = C2S; + else + badusage("Invalid direction (-D)"); + break; + case 'f': + data_path = optarg; + break; + case 'K': + kex = optarg; + break; + case 'k': + kpath = optarg; + break; + case 'i': + packet_index = atoi(optarg); + if (packet_index < 0) + badusage("Invalid packet index"); + break; + default: + badusage("unsupported flag"); + } + } + argc -= optind; + argv += optind; + + /* Must select a single mode */ + if ((count_flag + dump_flag + replace_flag) != 1) + badusage("Must select one mode: -c, -d or -r"); + /* KEX type is mandatory */ + if (kex == NULL || !kex_names_valid(kex) || strchr(kex, ',') != NULL) + badusage("Missing or invalid kex type (-K flag)"); + /* Valid key is mandatory */ + if (kpath == NULL) + badusage("Missing private key (-k flag)"); + if ((fd = open(kpath, O_RDONLY)) == -1) + err(1, "open %s", kpath); + if ((r = sshkey_load_private_type_fd(fd, KEY_UNSPEC, NULL, + &key, NULL)) != 0) + errx(1, "Unable to load key %s: %s", kpath, ssh_err(r)); + close(fd); + /* XXX check that it is a private key */ + /* XXX support certificates */ + if (key == NULL || key->type == KEY_UNSPEC || key->type == KEY_RSA1) + badusage("Invalid key file (-k flag)"); + + /* Replace (fuzz) mode */ + if (replace_flag) { + if (packet_index == -1 || direction == -1 || data_path == NULL) + badusage("Replace (-r) mode must specify direction " + "(-D) packet index (-i) and data path (-f)"); + if ((fd = open(data_path, O_RDONLY)) == -1) + err(1, "open %s", data_path); + replace_data = sshbuf_new(); + if ((r = sshkey_load_file(fd, replace_data)) != 0) + errx(1, "read %s: %s", data_path, ssh_err(r)); + close(fd); + } + + /* Dump mode */ + if (dump_flag) { + if (packet_index == -1 || direction == -1 || data_path == NULL) + badusage("Dump (-d) mode must specify direction " + "(-D), packet index (-i) and data path (-f)"); + } + + /* Count mode needs no further flags */ + + do_kex_with_key(kex, key, &c2s, &s2c, + direction, packet_index, + dump_flag ? data_path : NULL, + replace_flag ? replace_data : NULL); + sshkey_free(key); + sshbuf_free(replace_data); + + if (count_flag) { + printf("S2C: %d\n", s2c); + printf("C2S: %d\n", c2s); + } + + return 0; +} -- cgit v1.2.3 From c425494d6b6181beb54a1b3763ef9e944fd3c214 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 8 Mar 2016 14:03:54 -0800 Subject: unbreak kexfuzz for -Werror without __bounded__ --- regress/misc/kexfuzz/kexfuzz.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'regress/misc/kexfuzz') diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c index d57a117ac..0a4eabc43 100644 --- a/regress/misc/kexfuzz/kexfuzz.c +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -5,6 +5,8 @@ * Placed in the public domain */ +#include "includes.h" + #include #include #include -- cgit v1.2.3 From e960051f9a264f682c4d2fefbeecffcfc66b0ddf Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Wed, 9 Mar 2016 13:14:18 +1100 Subject: Wrap stdint.h inside #ifdef HAVE_STDINT_H. --- regress/misc/kexfuzz/kexfuzz.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'regress/misc/kexfuzz') diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c index 0a4eabc43..e6751d31c 100644 --- a/regress/misc/kexfuzz/kexfuzz.c +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -10,7 +10,9 @@ #include #include #include -#include +#ifdef HAVE_STDINT_H +# include +#endif #include #include #include -- cgit v1.2.3 From 6310ef27a2567cda66d6cf0c1ad290ee1167f243 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Wed, 13 Jul 2016 14:42:35 +1000 Subject: Move err.h replacements into compat lib. Move implementations of err.h replacement functions into their own file in the libopenbsd-compat so we can use them in kexfuzz.c too. ok djm@ --- configure.ac | 4 +++ openbsd-compat/Makefile.in | 2 +- openbsd-compat/bsd-err.c | 71 ++++++++++++++++++++++++++++++++++++++++++ openbsd-compat/bsd-misc.h | 11 +++++++ regress/misc/kexfuzz/kexfuzz.c | 4 ++- regress/netcat.c | 40 ------------------------ 6 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 openbsd-compat/bsd-err.c (limited to 'regress/misc/kexfuzz') diff --git a/configure.ac b/configure.ac index 2bb5a63c8..005a9ead5 100644 --- a/configure.ac +++ b/configure.ac @@ -373,6 +373,7 @@ AC_CHECK_HEADERS([ \ dirent.h \ endian.h \ elf.h \ + err.h \ features.h \ fcntl.h \ floatingpoint.h \ @@ -1692,6 +1693,8 @@ AC_CHECK_FUNCS([ \ closefrom \ dirfd \ endgrent \ + err \ + errx \ explicit_bzero \ fchmod \ fchown \ @@ -1783,6 +1786,7 @@ AC_CHECK_FUNCS([ \ vasprintf \ vsnprintf \ waitpid \ + warn \ ]) AC_LINK_IFELSE( diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index 3c5e3b7f7..aca9eba75 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@ OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o -COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o +COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o diff --git a/openbsd-compat/bsd-err.c b/openbsd-compat/bsd-err.c new file mode 100644 index 000000000..ab10646f0 --- /dev/null +++ b/openbsd-compat/bsd-err.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Tim Rice + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h" + +#ifndef HAVE_ERR +void +err(int r, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", strerror(errno)); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + exit(r); +} +#endif + +#ifndef HAVE_ERRX +void +errx(int r, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); + exit(r); +} +#endif + +#ifndef HAVE_WARN +void +warn(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", strerror(errno)); + vfprintf(stderr, fmt, args); + fputc('\n', stderr); + va_end(args); +} +#endif diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index 0d81d1735..27abb2e92 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h @@ -126,4 +126,15 @@ pid_t getpgid(pid_t); int pledge(const char *promises, const char *paths[]); #endif +/* bsd-err.h */ +#ifndef HAVE_ERR +void err(int, const char *, ...) __attribute__((format(printf, 2, 3))); +#endif +#ifndef HAVE_ERRX +void errx(int, const char *, ...) __attribute__((format(printf, 2, 3))); +#endif +#ifndef HAVE_WARN +void warn(const char *, ...) __attribute__((format(printf, 1, 2))); +#endif + #endif /* _BSD_MISC_H */ diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c index e6751d31c..2894d3a1e 100644 --- a/regress/misc/kexfuzz/kexfuzz.c +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -17,7 +17,9 @@ #include #include #include -#include +#ifdef HAVE_ERR_H +# include +#endif #include "ssherr.h" #include "ssh_api.h" diff --git a/regress/netcat.c b/regress/netcat.c index 6234ba019..7c29e0cf9 100644 --- a/regress/netcat.c +++ b/regress/netcat.c @@ -134,46 +134,6 @@ void usage(int); ssize_t drainbuf(int, unsigned char *, size_t *); ssize_t fillbuf(int, unsigned char *, size_t *); -static void err(int, const char *, ...) __attribute__((format(printf, 2, 3))); -static void errx(int, const char *, ...) __attribute__((format(printf, 2, 3))); -static void warn(const char *, ...) __attribute__((format(printf, 1, 2))); - -static void -err(int r, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, "%s: ", strerror(errno)); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - va_end(args); - exit(r); -} - -static void -errx(int r, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - va_end(args); - exit(r); -} - -static void -warn(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, "%s: ", strerror(errno)); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - va_end(args); -} int main(int argc, char *argv[]) -- cgit v1.2.3