[31548] in CVS-changelog-for-Kerberos-V5
krb5 commit: Add OSS-Fuzz target for ccache marshalling
daemon@ATHENA.MIT.EDU (ghudson@mit.edu)
Sat Jun 13 02:55:18 2026
From: ghudson@mit.edu
To: cvs-krb5@mit.edu
Message-Id: <20260613065511.7246B105580@krbdev.mit.edu>
Date: Sat, 13 Jun 2026 02:55:11 -0400 (EDT)
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu
https://github.com/krb5/krb5/commit/63b55949eff0ac47202d3d717d5b68ebad2fc6b1
commit 63b55949eff0ac47202d3d717d5b68ebad2fc6b1
Author: Arthur Chan <arthur.chan@adalogics.com>
Date: Thu Jun 11 12:49:35 2026 +0100
Add OSS-Fuzz target for ccache marshalling
.gitignore | 1 +
src/tests/fuzzing/Makefile.in | 6 +
src/tests/fuzzing/deps | 10 ++
src/tests/fuzzing/fuzz_ccache.c | 133 +++++++++++++++++++++
.../fuzz_ccache_seed_corpus/v1_principal_only | Bin 0 -> 27 bytes
.../fuzz_ccache_seed_corpus/v4_principal_only | Bin 0 -> 29 bytes
src/tests/fuzzing/oss-fuzz.sh | 9 +-
7 files changed, 155 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index d4e978349..c7e18066a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -437,6 +437,7 @@ local.properties
/src/tests/fuzzing/fuzz_aes
/src/tests/fuzzing/fuzz_asn
/src/tests/fuzzing/fuzz_attrset
+/src/tests/fuzzing/fuzz_ccache
/src/tests/fuzzing/fuzz_chpw
/src/tests/fuzzing/fuzz_crypto
/src/tests/fuzzing/fuzz_des
diff --git a/src/tests/fuzzing/Makefile.in b/src/tests/fuzzing/Makefile.in
index 15bbbbf1a..d6aafc17b 100644
--- a/src/tests/fuzzing/Makefile.in
+++ b/src/tests/fuzzing/Makefile.in
@@ -11,6 +11,7 @@ OBJS= \
fuzz_aes.o \
fuzz_asn.o \
fuzz_attrset.o \
+ fuzz_ccache.o \
fuzz_chpw.o \
fuzz_crypto.o \
fuzz_des.o \
@@ -32,6 +33,7 @@ SRCS= \
$(srcdir)/fuzz_aes.c \
$(srcdir)/fuzz_asn.c \
$(srcdir)/fuzz_attrset.c \
+ $(srcdir)/fuzz_ccache.c \
$(srcdir)/fuzz_chpw.c \
$(srcdir)/fuzz_crypto.c \
$(srcdir)/fuzz_des.c \
@@ -53,6 +55,7 @@ FUZZ_TARGETS= \
fuzz_aes \
fuzz_asn \
fuzz_attrset \
+ fuzz_ccache \
fuzz_chpw \
fuzz_crypto \
fuzz_des \
@@ -84,6 +87,9 @@ fuzz_asn: fuzz_asn.o $(KRB5_BASE_DEPLIBS)
fuzz_attrset: fuzz_attrset.o $(KRB5_BASE_DEPLIBS)
$(CXX_LINK) -o $@ fuzz_attrset.o -lkrad $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
+fuzz_ccache: fuzz_ccache.o $(KRB5_BASE_DEPLIBS)
+ $(CXX_LINK) -o $@ fuzz_ccache.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
+
fuzz_chpw: fuzz_chpw.o $(KRB5_BASE_DEPLIBS)
$(CXX_LINK) -o $@ fuzz_chpw.o $(KRB5_BASE_LIBS) $(FUZZ_LDFLAGS)
diff --git a/src/tests/fuzzing/deps b/src/tests/fuzzing/deps
index fbd77e8ea..539d4fd2e 100644
--- a/src/tests/fuzzing/deps
+++ b/src/tests/fuzzing/deps
@@ -35,6 +35,16 @@ $(OUTPRE)fuzz_attrset.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
fuzz_attrset.c
+$(OUTPRE)fuzz_ccache.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h fuzz_ccache.c
$(OUTPRE)fuzz_chpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
diff --git a/src/tests/fuzzing/fuzz_ccache.c b/src/tests/fuzzing/fuzz_ccache.c
new file mode 100644
index 000000000..ae79d4087
--- /dev/null
+++ b/src/tests/fuzzing/fuzz_ccache.c
@@ -0,0 +1,133 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/fuzzing/fuzz_ccache.c - fuzzing harness for the FILE ccache parser */
+/*
+ * Copyright (C) 2026 by Arthur Chan. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+/*
+ * This harness fuzzes the FILE credential cache parser in
+ * lib/krb5/ccache/cc_file.c. The fuzz input is written verbatim to a
+ * temporary file, which is then resolved as a "FILE:" ccache and read back;
+ * then the cache's default principal is fetched and its credentials are
+ * iterated to drive the parser (version, header, principal and credential
+ * unmarshalling).
+ */
+
+#include <k5-int.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define kMinInputLength 2
+#define kMaxInputLength 4096
+
+extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+/* krb5_init_context is expensive, so create the context once and reuse it. */
+static krb5_context
+get_context(void)
+{
+ static krb5_context context = NULL;
+ static int initialized = 0;
+
+ if (!initialized) {
+ initialized = 1;
+ if (krb5_init_context(&context) != 0)
+ context = NULL;
+ }
+ return context;
+}
+
+/* Iterate over every credential in the cache to exercise the parser. */
+static void
+iterate_creds(krb5_context context, krb5_ccache ccache)
+{
+ krb5_error_code ret;
+ krb5_cc_cursor cursor;
+ krb5_creds cred;
+
+ ret = krb5_cc_start_seq_get(context, ccache, &cursor);
+ if (ret)
+ return;
+
+ while (krb5_cc_next_cred(context, ccache, &cursor, &cred) == 0)
+ krb5_free_cred_contents(context, &cred);
+
+ krb5_cc_end_seq_get(context, ccache, &cursor);
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_ccache ccache;
+ krb5_principal princ;
+ char tmpl[] = "/tmp/fuzz_ccache.XXXXXX";
+ char name[64];
+ int fd;
+
+ if (size < kMinInputLength || size > kMaxInputLength)
+ return 0;
+
+ context = get_context();
+ if (context == NULL)
+ return 0;
+
+ /* Write the fuzz input to a temporary file. */
+ fd = mkstemp(tmpl);
+ if (fd < 0)
+ return 0;
+ if (write(fd, data, size) != (ssize_t)size) {
+ close(fd);
+ unlink(tmpl);
+ return 0;
+ }
+ close(fd);
+
+ snprintf(name, sizeof(name), "FILE:%s", tmpl);
+
+ ret = krb5_cc_resolve(context, name, &ccache);
+ if (ret) {
+ unlink(tmpl);
+ return 0;
+ }
+
+ /* Fetch the default principal, then walk the credentials. */
+ ret = krb5_cc_get_principal(context, ccache, &princ);
+ if (!ret)
+ krb5_free_principal(context, princ);
+
+ iterate_creds(context, ccache);
+
+ krb5_cc_close(context, ccache);
+ unlink(tmpl);
+
+ return 0;
+}
diff --git a/src/tests/fuzzing/fuzz_ccache_seed_corpus/v1_principal_only b/src/tests/fuzzing/fuzz_ccache_seed_corpus/v1_principal_only
new file mode 100644
index 000000000..dab7e2fa6
Binary files /dev/null and b/src/tests/fuzzing/fuzz_ccache_seed_corpus/v1_principal_only differ
diff --git a/src/tests/fuzzing/fuzz_ccache_seed_corpus/v4_principal_only b/src/tests/fuzzing/fuzz_ccache_seed_corpus/v4_principal_only
new file mode 100644
index 000000000..6dde9d673
Binary files /dev/null and b/src/tests/fuzzing/fuzz_ccache_seed_corpus/v4_principal_only differ
diff --git a/src/tests/fuzzing/oss-fuzz.sh b/src/tests/fuzzing/oss-fuzz.sh
index b01d4bcbd..313adfc53 100644
--- a/src/tests/fuzzing/oss-fuzz.sh
+++ b/src/tests/fuzzing/oss-fuzz.sh
@@ -15,10 +15,11 @@ popd
# Copy fuzz targets and seed corpus to $OUT.
pushd src/tests/fuzzing
-fuzzers=("fuzz_aes" "fuzz_asn" "fuzz_attrset" "fuzz_chpw" "fuzz_crypto"
- "fuzz_des" "fuzz_gss" "fuzz_json" "fuzz_kdc" "fuzz_krad" "fuzz_krb"
- "fuzz_krb5_ticket" "fuzz_marshal_cred" "fuzz_marshal_princ"
- "fuzz_ndr" "fuzz_oid" "fuzz_pac" "fuzz_profile" "fuzz_util")
+fuzzers=("fuzz_aes" "fuzz_asn" "fuzz_attrset" "fuzz_ccache" "fuzz_chpw"
+ "fuzz_crypto" "fuzz_des" "fuzz_gss" "fuzz_json" "fuzz_kdc"
+ "fuzz_krad" "fuzz_krb" "fuzz_krb5_ticket" "fuzz_marshal_cred"
+ "fuzz_marshal_princ" "fuzz_ndr" "fuzz_oid" "fuzz_pac" "fuzz_profile"
+ "fuzz_util")
for fuzzer in "${fuzzers[@]}"; do
cp "$fuzzer" "$OUT/$fuzzer"
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5