[openssh-commits] [openssh] 03/15: OSS-Fuzz: Add fuzzer targets authfd reply message handling
git+noreply at mindrot.org
git+noreply at mindrot.org
Fri Oct 9 21:38:21 AEDT 2026
This is an automated email from the git hooks/post-receive script.
dtucker pushed a commit to branch master
in repository openssh.
commit 4c29d4f512863436490cd5fb1f0bf1f02be83719
Author: Arthur Chan <arthur.chan at adalogics.com>
AuthorDate: Wed May 27 18:45:21 2026 +0100
OSS-Fuzz: Add fuzzer targets authfd reply message handling
Signed-off-by: Arthur Chan <arthur.chan at adalogics.com>
---
regress/misc/fuzz-harness/Makefile | 5 +-
regress/misc/fuzz-harness/authfd_reply_fuzz.cc | 180 +++++++++++++++++++++++++
2 files changed, 184 insertions(+), 1 deletion(-)
diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile
index d8b86d4a9..90132311c 100644
--- a/regress/misc/fuzz-harness/Makefile
+++ b/regress/misc/fuzz-harness/Makefile
@@ -15,7 +15,7 @@ COMMON_DEPS=../../../libssh.a $(COMMON_OBJS)
TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz authkeys_fuzz sshsig_fuzz \
sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz \
mkcorpus_sntrup761 sntrup761_enc_fuzz sntrup761_dec_fuzz \
- ssh_client_session_fuzz sftp_server_msg_fuzz
+ ssh_client_session_fuzz sftp_server_msg_fuzz authfd_reply_fuzz
all: $(TARGETS)
@@ -64,6 +64,9 @@ sftp_server_msg_fuzz: sftp_server_msg_fuzz.o sftp_server_msg_fuzz_helper.o fuzz_
sftp_server_msg_fuzz_helper.o: sftp_server_msg_fuzz_helper.c ../../../sftp-server.c
+authfd_reply_fuzz: authfd_reply_fuzz.o fuzz_arena.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ authfd_reply_fuzz.o fuzz_arena.o $(SK_NULL_OBJS) -Wl,--wrap=malloc,--wrap=calloc,--wrap=realloc,--wrap=free,--wrap=strdup $(LDFLAGS) $(FUZZ_FLAGS) $(LIBS)
+
sk-dummy.o: ../sk-dummy/sk-dummy.c
$(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) $(FUZZ_FLAGS)
diff --git a/regress/misc/fuzz-harness/authfd_reply_fuzz.cc b/regress/misc/fuzz-harness/authfd_reply_fuzz.cc
new file mode 100644
index 000000000..7d1e2e483
--- /dev/null
+++ b/regress/misc/fuzz-harness/authfd_reply_fuzz.cc
@@ -0,0 +1,180 @@
+/* Copyright 2026 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/*
+ * Fuzzer for OpenSSH agent client reply parser (authfd.c)
+ *
+ * Target: authfd.c
+ *
+ * Drives every public agent client API on a socketpair using the
+ * fuzzer input as the reply payload. A helper opens a fresh
+ * socketpair, frames the body as a length-prefixed agent reply,
+ * invokes one API, and resets state via fuzz_arena_cleanup before
+ * the next call. Each iteration runs all five APIs on the same
+ * input so no API is starved by a selector byte.
+ *
+ * Primary functions exercised:
+ * - ssh_fetch_identitylist
+ * - ssh_agent_sign
+ * - ssh_agent_has_key
+ * - ssh_agent_query_extensions
+ * - ssh_lock_agent
+ *
+ * Threat model: a malicious or compromised agent (via ForwardAgent
+ * to a hostile host) returning crafted replies. The client must
+ * parse them safely.
+ *
+ * fuzz_arena (linker --wrap'd malloc family) provides per-call heap
+ * cleanup so allocations not released by the code under test are
+ * reclaimed before the next call.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+extern "C" {
+#include "includes.h"
+#include "sshkey.h"
+#include "sshbuf.h"
+#include "ssherr.h"
+#include "authfd.h"
+#include "log.h"
+
+void fuzz_arena_begin(void);
+void fuzz_arena_cleanup(void);
+}
+
+#include "fixed-keys.h"
+
+static struct sshkey *test_keys[3] = { NULL, NULL, NULL };
+static int initialized = 0;
+
+static struct sshkey *
+load_pubkey_or_die(const char *txt)
+{
+ char *tmp, *cp;
+ struct sshkey *k;
+
+ if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
+ abort();
+ if ((tmp = cp = strdup(txt)) == NULL)
+ abort();
+ if (sshkey_read(k, &cp) != 0)
+ abort();
+ free(tmp);
+ return k;
+}
+
+static void
+setup(void)
+{
+ if (initialized)
+ return;
+ initialized = 1;
+ log_init("authfd_reply_fuzz", SYSLOG_LEVEL_ERROR,
+ SYSLOG_FACILITY_AUTH, 0);
+ test_keys[0] = load_pubkey_or_die(PUB_RSA);
+ test_keys[1] = load_pubkey_or_die(PUB_ECDSA);
+ test_keys[2] = load_pubkey_or_die(PUB_ED25519);
+}
+
+enum {
+ API_FETCH_IDENTITYLIST,
+ API_AGENT_SIGN,
+ API_AGENT_HAS_KEY,
+ API_QUERY_EXTENSIONS,
+ API_LOCK_AGENT,
+};
+
+static void
+run_one(int api, struct sshkey *k, int lock_arg,
+ const uint8_t *body, size_t bsize)
+{
+ int sv[2] = { -1, -1 };
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
+ return;
+
+ uint32_t blen = (uint32_t)bsize;
+ uint8_t hdr[4] = {
+ (uint8_t)(blen >> 24), (uint8_t)(blen >> 16),
+ (uint8_t)(blen >> 8), (uint8_t)(blen)
+ };
+ (void)write(sv[0], hdr, sizeof(hdr));
+ if (bsize > 0)
+ (void)write(sv[0], body, bsize);
+
+ fuzz_arena_begin();
+
+ switch (api) {
+ case API_FETCH_IDENTITYLIST: {
+ struct ssh_identitylist *idl = NULL;
+ (void)ssh_fetch_identitylist(sv[1], &idl);
+ ssh_free_identitylist(idl);
+ break;
+ }
+ case API_AGENT_SIGN: {
+ const u_char msg[16] = { 0 };
+ u_char *sig = NULL;
+ size_t siglen = 0;
+ (void)ssh_agent_sign(sv[1], k, &sig, &siglen,
+ msg, sizeof(msg), NULL, 0);
+ free(sig);
+ break;
+ }
+ case API_AGENT_HAS_KEY:
+ (void)ssh_agent_has_key(sv[1], k);
+ break;
+ case API_QUERY_EXTENSIONS: {
+ char **exts = NULL;
+ int n = ssh_agent_query_extensions(sv[1], &exts);
+ if (n == 0 && exts != NULL) {
+ for (int i = 0; exts[i] != NULL; i++)
+ free(exts[i]);
+ free(exts);
+ }
+ break;
+ }
+ case API_LOCK_AGENT:
+ (void)ssh_lock_agent(sv[1], lock_arg, "fuzz");
+ break;
+ }
+
+ fuzz_arena_cleanup();
+
+ close(sv[0]);
+ close(sv[1]);
+}
+
+extern "C" int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ setup();
+
+ if (size > 65536)
+ return 0;
+
+ run_one(API_FETCH_IDENTITYLIST, NULL, 0, data, size);
+ run_one(API_AGENT_SIGN, test_keys[0], 0, data, size);
+ run_one(API_AGENT_SIGN, test_keys[1], 0, data, size);
+ run_one(API_AGENT_SIGN, test_keys[2], 0, data, size);
+ run_one(API_AGENT_HAS_KEY, test_keys[2], 0, data, size);
+ run_one(API_QUERY_EXTENSIONS, NULL, 0, data, size);
+ run_one(API_LOCK_AGENT, NULL, 1, data, size);
+
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list